Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 В CTE получается декартово произведение  [new]
карабаскин
Guest
Всем привет!

Изучаю СTE. Вот такой запросец
;WITH fio AS (
	SELECT 'Иванов   Иван   Иванович' AS fio UNION ALL
	SELECT 'Петров  Петр    Петрович' UNION ALL
	SELECT 'Степанов     Степан Степанович'
), 
	f1 AS (SELECT SUBSTRING(fio, 1, CHARINDEX(' ', [fio]) - 1) AS SurName FROM [fio]),
	g1 AS (SELECT LTRIM(SUBSTRING(fio, CHARINDEX(' ', [fio]) + 1, LEN(fio))) AS fio FROM [fio]),
	f2 AS (SELECT SUBSTRING(fio, 1, CHARINDEX(' ', [fio]) - 1) AS [Name] FROM [g1]),
	f3 AS (SELECT LTRIM(SUBSTRING(fio, CHARINDEX(' ', [fio]) + 1, LEN(fio))) AS [SecName] FROM [g1])
SELECT
	*
FROM fio, f1, f2, f3
Получается декартово произведение. Как этого избежать?
26 июн 09, 16:23    [7349214]     Ответить | Цитировать Сообщить модератору
 Re: В CTE получается декартово произведение  [new]
Maxx
Member [скрыт]

Откуда:
Сообщений: 24290
наверное написать селект без него
-------------------------------------
Jedem Das Seine
26 июн 09, 16:25    [7349234]     Ответить | Цитировать Сообщить модератору
 Re: В CTE получается декартово произведение  [new]
карабаскин
Guest
Maxx
наверное написать селект без него
-------------------------------------
Jedem Das Seine
Это как? Через производные таблицы что ли? Не хочу
26 июн 09, 16:27    [7349249]     Ответить | Цитировать Сообщить модератору
 Re: В CTE получается декартово произведение  [new]
Glory
Member

Откуда:
Сообщений: 104760
карабаскин
Maxx
наверное написать селект без него
-------------------------------------
Jedem Das Seine
Это как? Через производные таблицы что ли? Не хочу

А вы думаете, что если вы во FROM fio, f1, f2, f3 не укажете условия соединения, то сервер это за вас сделает что ли ?
26 июн 09, 16:29    [7349265]     Ответить | Цитировать Сообщить модератору
 Re: В CTE получается декартово произведение  [new]
Паганель
Member

Откуда: Винница
Сообщений: 22552
карабаскин
Получается декартово произведение. Как этого избежать?
Сообщить серверу, по каким принципам он должен соединять строки разных cte между собой

И еще желательно прекратить применение запятой в кляюзе from,
а писать вместо них явно join-ы
26 июн 09, 16:30    [7349271]     Ответить | Цитировать Сообщить модератору
 Re: В CTE получается декартово произведение  [new]
Бабичев Сергей
Member

Откуда: Красноярск
Сообщений: 2497
;WITH fio_1 AS (
	SELECT 'Иванов   Иван   Иванович' AS fio UNION ALL
	SELECT 'Петров  Петр    Петрович' UNION ALL
	SELECT 'Степанов     Степан Степанович'
), 
fio as (select row_number() over(order by fio) as rn, t.* from fio_1 t)
	f1 AS (SELECT rn, SUBSTRING(fio, 1, CHARINDEX(' ', [fio]) - 1) AS SurName FROM [fio]),
	g1 AS (SELECT rn, LTRIM(SUBSTRING(fio, CHARINDEX(' ', [fio]) + 1, LEN(fio))) AS fio FROM [fio]),
	f2 AS (SELECT rn, SUBSTRING(fio, 1, CHARINDEX(' ', [fio]) - 1) AS [Name] FROM [g1]),
	f3 AS (SELECT rn, LTRIM(SUBSTRING(fio, CHARINDEX(' ', [fio]) + 1, LEN(fio))) AS [SecName] FROM [g1])
SELECT
	*
FROM fio, f1, f2, f3
where fio.rn = f1.rn
 and fio.rn = f2.rn
 and fio.rn = f3.rn;
26 июн 09, 16:32    [7349285]     Ответить | Цитировать Сообщить модератору
 Re: В CTE получается декартово произведение  [new]
карабаскин
Guest
Glory
А вы думаете, что если вы во FROM fio, f1, f2, f3 не укажете условия соединения, то сервер это за вас сделает что ли ?
Я знаю понимаю что надо указать, только не врублюсь как.
26 июн 09, 16:32    [7349286]     Ответить | Цитировать Сообщить модератору
 Re: В CTE получается декартово произведение  [new]
Бабичев Сергей
Member

Откуда: Красноярск
Сообщений: 2497
А, пардон, запятую-то забыл...
Бабичев Сергей
;WITH fio_1 AS (
	SELECT 'Иванов   Иван   Иванович' AS fio UNION ALL
	SELECT 'Петров  Петр    Петрович' UNION ALL
	SELECT 'Степанов     Степан Степанович'
), 
 fio as (select row_number() over(order by fio) as rn, t.* from fio_1 t),
	f1 AS (SELECT rn, SUBSTRING(fio, 1, CHARINDEX(' ', [fio]) - 1) AS SurName FROM [fio]),
	g1 AS (SELECT rn, LTRIM(SUBSTRING(fio, CHARINDEX(' ', [fio]) + 1, LEN(fio))) AS fio FROM [fio]),
	f2 AS (SELECT rn, SUBSTRING(fio, 1, CHARINDEX(' ', [fio]) - 1) AS [Name] FROM [g1]),
	f3 AS (SELECT rn, LTRIM(SUBSTRING(fio, CHARINDEX(' ', [fio]) + 1, LEN(fio))) AS [SecName] FROM [g1])
SELECT
	*
FROM fio, f1, f2, f3
where fio.rn = f1.rn
 and fio.rn = f2.rn
 and fio.rn = f3.rn;

:)
26 июн 09, 16:34    [7349303]     Ответить | Цитировать Сообщить модератору
 Re: В CTE получается декартово произведение  [new]
Паганель
Member

Откуда: Винница
Сообщений: 22552
Вообще, глядя на задачу шире, автору лучше было бы спросить у форума, как убрать лишние пробелы
(или поиском тут же найти, обсуждалось неоднократно),
потом REPLACE (Transact-SQL)
а потом просто PARSENAME (Transact-SQL)
26 июн 09, 16:39    [7349339]     Ответить | Цитировать Сообщить модератору
 Re: В CTE получается декартово произведение  [new]
карабаскин
Guest
Бабичев Сергей,

Спасибо. Это исправить мне по силам :)

Теперь, правда, новая напасть.
;WITH fio_1 AS (
	SELECT 'Иванов' AS fio), 
fio as (select row_number() over(order by fio) as rn, t.* from fio_1 t),
	f1 AS (SELECT rn, SUBSTRING(fio, 1, CHARINDEX(' ', [fio]) - 1) AS SurName FROM [fio]),
	g1 AS (SELECT rn, LTRIM(SUBSTRING(fio, CHARINDEX(' ', [fio]) + 1, LEN(fio))) AS fio FROM [fio]),
	f2 AS (SELECT rn, SUBSTRING(fio, 1, CHARINDEX(' ', [fio]) - 1) AS [Name] FROM [g1]),
	f3 AS (SELECT rn, LTRIM(SUBSTRING(fio, CHARINDEX(' ', [fio]) + 1, LEN(fio))) AS [SecName] FROM [g1])
SELECT
	*
FROM fio, f1, f2, f3
where fio.rn = f1.rn
 and fio.rn = f2.rn
 and fio.rn = f3.rn;
Msg 536, Level 16, State 5, Line 1
Недопустимый параметр длины передан функции SUBSTRING.
:(
26 июн 09, 16:40    [7349351]     Ответить | Цитировать Сообщить модератору
 Re: В CTE получается декартово произведение  [new]
Senya_L
Member

Откуда: Москва
Сообщений: 5381
Паганель
Вообще, глядя на задачу шире, автору лучше было бы спросить у форума, как убрать лишние пробелы
(или поиском тут же найти, обсуждалось неоднократно),
потом REPLACE (Transact-SQL)
а потом просто PARSENAME (Transact-SQL)
Разве это шире? :)
26 июн 09, 16:42    [7349366]     Ответить | Цитировать Сообщить модератору
 Re: В CTE получается декартово произведение  [new]
Паганель
Member

Откуда: Винница
Сообщений: 22552
Ну не знаю как сказать... ширше или ширее...
Автору надо побить ФИО на части, если я правильно понял...
26 июн 09, 16:44    [7349376]     Ответить | Цитировать Сообщить модератору
 Re: В CTE получается декартово произведение  [new]
PaulYoung
Member

Откуда: Москва
Сообщений: 2549
карабаскин,

Не претендуя на оригинальность и оптимальность

CREATE FUNCTION GET_FIO_NAME_PART (@Name varchar(512), @NamePart int)
RETURNS varchar(128)
AS
BEGIN
	DECLARE @Result varchar(128)
	DECLARE @TString varchar(512), @SPart varchar(128)
	DECLARE @Table TABLE (id int IDENTITY(1, 1), nm varchar(128))

	SET @TString = @Name

	WHILE (CHARINDEX(' ', @TString) > 0)
	BEGIN
		SET @SPart = RTRIM(LEFT(@TString, CHARINDEX(' ', @TString) - 1))
		INSERT @Table (nm) VALUES(@SPart)
		SET @TString = LTRIM(RIGHT(@TString, LEN(@TString) - LEN(@SPart)))
	END

	INSERT @Table (nm) VALUES(@TString)
	
	SELECT @Result = nm
	FROM @Table
	WHERE id = @NamePart

	RETURN ISNULL(@Result, '')
END
GO
DECLARE @FIO varchar(256)

SET @FIO = 'Иванов'

SELECT
  dbo.GET_FIO_NAME_PART(@FIO, 1) AS F,
  dbo.GET_FIO_NAME_PART(@FIO, 2) AS I,
  dbo.GET_FIO_NAME_PART(@FIO, 3) AS O

SET @FIO = 'Иванов Иван'

SELECT
  dbo.GET_FIO_NAME_PART(@FIO, 1) AS F,
  dbo.GET_FIO_NAME_PART(@FIO, 2) AS I,
  dbo.GET_FIO_NAME_PART(@FIO, 3) AS O

SET @FIO = 'Иванов    Иван    Иваныч'

SELECT
  dbo.GET_FIO_NAME_PART(@FIO, 1) AS F,
  dbo.GET_FIO_NAME_PART(@FIO, 2) AS I,
  dbo.GET_FIO_NAME_PART(@FIO, 3) AS O
26 июн 09, 17:18    [7349619]     Ответить | Цитировать Сообщить модератору
 Re: В CTE получается декартово произведение  [new]
карабаскин
Guest
Спасибо большое всем. Я ошибку сделал что такай пример взял. Просто не хотел в пятницу людям голову забивать своей задачей и взячл пахожую. :( Я то думал что CTE это ну почти тоже самое что и производные таблицы. А вот и нет оказалось. Тему прошу считать закрытой.
26 июн 09, 17:26    [7349658]     Ответить | Цитировать Сообщить модератору
 Re: В CTE получается декартово произведение  [new]
iap
Member

Откуда: Москва
Сообщений: 46975
Паганель
Автору надо побить ФИО на части, если я правильно понял...
Вот эта тема не об этом ли?
26 июн 09, 18:11    [7349986]     Ответить | Цитировать Сообщить модератору
 Re: В CTE получается декартово произведение  [new]
Паганель
Member

Откуда: Винница
Сообщений: 22552
если это вопрос ко мне, то - да, эта тема действительно об этом
26 июн 09, 18:42    [7350138]     Ответить | Цитировать Сообщить модератору
 Re: В CTE получается декартово произведение  [new]
iap
Member

Откуда: Москва
Сообщений: 46975
Паганель
если это вопрос ко мне, то - да, эта тема действительно об этом
Это такой риторический вопрос
26 июн 09, 18:44    [7350148]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить