Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 Ради интереса  [new]
Semen81
Member

Откуда:
Сообщений: 160
Всем привет!!! Интересует решение следующей задачки, причем хотелось бы решить ее не использую цикл, если это возможно, т.к. ее реализовал с применением его. Есть запись в таблице типа:
Наименование Количество Сумма
Калькулятор 3 150


Возможно ли запросом получить на выходе таблицу следующего вида:
Наименование Количество Цена
Калькулятор 1 50
Калькулятор 1 50
Калькулятор 1 50


Т.е. мы одну строку преобразовали в 3, т.к. количество 3. Если будет количество 20, то на выходе получаем 20 строк?
Это только ради любопытства. Задача решилась с использованием цикла, но хотелось бы ради повышения самообразованности увидеть другие оригинальные решения. Всем спасибо!!!!
27 сен 11, 12:42    [11340975]     Ответить | Цитировать Сообщить модератору
 Re: Ради интереса  [new]
tt1
Guest
нужно взять табличку с целой числовой последовательностью t, в которой строк заведомо больше чем максимальное значение в поле "Количество" и сделать с ней джойн по неравенству, чтобы количество было меньше или равно значению целого из таблицы t
27 сен 11, 12:56    [11341128]     Ответить | Цитировать Сообщить модератору
 Re: Ради интереса  [new]
mike909
Member

Откуда:
Сообщений: 662
Semen81,

DECLARE @t TABLE(NAME SYSNAME, cnt INT, sm INT )

INSERT INTO @t VALUES( 'Калькулятор', 3,150)

;with L0 as (select 0 x union all select 0),
     L1 as (select 0 x from L0 t1, L0 t2),
     L2 as (select 0 x from L1 t1, L1 t2),
     L3 as (select 0 x from L2 t1, L2 t2),
     L4 as (select 0 x from L3 t1, L3 t2),
     L5 as (select row_number() over(order by (select 1)) N from L4 t1, L4 t2)
select *
FROM @t AS t
CROSS APPLY(
  SELECT TOP( t.cnt ) sm / t.cnt AS [Res]
  FROM L5 
) AS r
27 сен 11, 12:57    [11341148]     Ответить | Цитировать Сообщить модератору
 Re: Ради интереса  [new]
Semen81
Member

Откуда:
Сообщений: 160
mike909
Semen81,

DECLARE @t TABLE(NAME SYSNAME, cnt INT, sm INT )

INSERT INTO @t VALUES( 'Калькулятор', 3,150)

;with L0 as (select 0 x union all select 0),
     L1 as (select 0 x from L0 t1, L0 t2),
     L2 as (select 0 x from L1 t1, L1 t2),
     L3 as (select 0 x from L2 t1, L2 t2),
     L4 as (select 0 x from L3 t1, L3 t2),
     L5 as (select row_number() over(order by (select 1)) N from L4 t1, L4 t2)
select *
FROM @t AS t
CROSS APPLY(
  SELECT TOP( t.cnt ) sm / t.cnt AS [Res]
  FROM L5 
) AS r


Да уж, век живи - век учись!!!! Прикольно, но без бутылки не разберусь ))))
27 сен 11, 13:39    [11341507]     Ответить | Цитировать Сообщить модератору
 Re: Ради интереса  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
mike909
CROSS APPLY(SELECT TOP(t.cnt)
Чёрт возми, я первый раз это вижу ... на форуме.
27 сен 11, 16:30    [11343226]     Ответить | Цитировать Сообщить модератору
 Re: Ради интереса  [new]
А.Н.
Member

Откуда: Санкт-Петербург
Сообщений: 1
Mnior
mike909
CROSS APPLY(SELECT TOP(t.cnt)
Чёрт возми, я первый раз это вижу ... на форуме.


Почему такая реакция?
27 сен 11, 19:11    [11344440]     Ответить | Цитировать Сообщить модератору
 Re: Ради интереса  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
А.Н.
Почему такая реакция?
Целый пласт установлен в статус unresolved, сбиты внутренние счётчики. Надо переосмыслять, но конкретных ссылок на топики-задач то не найти (в этом месиве).

Вот если iljy или iap или ктось есчё равный скажет, что мол:
а) 100 раз писали (тынц, тынц)
б) да почти нигде не применимо (ни в каких задачках)
То мне станет легче - или пропустил, развивается склероз или реально банально ничего особенного. Но может же что - "Усе проффтыкали" (актуально для постояльцев).
28 сен 11, 00:33    [11345463]     Ответить | Цитировать Сообщить модератору
 Re: Ради интереса  [new]
kDnZP
Member [заблокирован]

Откуда: ★[msg=16399436]★[msg=20850760]
Сообщений: 11289
Mnior, редкоприменяемо (да и то с 2005 начиная), вон рядом про ntile вспомнили - тоже раз в 100 лет бывает.
28 сен 11, 00:54    [11345486]     Ответить | Цитировать Сообщить модератору
 Re: Ради интереса  [new]
mike909
Member

Откуда:
Сообщений: 662
Mnior
А.Н.
Почему такая реакция?
Целый пласт установлен в статус unresolved, сбиты внутренние счётчики. Надо переосмыслять, но конкретных ссылок на топики-задач то не найти (в этом месиве).

Вот если iljy или iap или ктось есчё равный скажет, что мол:
а) 100 раз писали (тынц, тынц)
б) да почти нигде не применимо (ни в каких задачках)
То мне станет легче - или пропустил, развивается склероз или реально банально ничего особенного. Но может же что - "Усе проффтыкали" (актуально для постояльцев).

+1 на счет "а" и "б"
+ А вот на счет остального
Переменные чистить надо (С) ... про Буратина с яблоками ...
Ну или курить что-нибудь по легче
28 сен 11, 00:58    [11345490]     Ответить | Цитировать Сообщить модератору
 Re: Ради интереса  [new]
так,
Guest
Mnior
...
б) да почти нигде не применимо (ни в каких задачках)

да, - редко, но иногда "эффект применения" просто "выносит"
Запрос с датами
28 сен 11, 07:05    [11345625]     Ответить | Цитировать Сообщить модератору
 Re: Ради интереса  [new]
J.d
Member

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

не смешите мои тапочки

;WITH c AS 
(		SELECT [n] = 1
		UNION ALL
		SELECT [n] = c.[n] + 1
		FROM c
)
SELECT * FROM c

и join этого с исходной таблицей по полю количество
28 сен 11, 10:48    [11346331]     Ответить | Цитировать Сообщить модератору
 Re: Ради интереса  [new]
invm
Member

Откуда: Москва
Сообщений: 9836
J.d
mike909,

не смешите мои тапочки

;WITH c AS 
(		SELECT [n] = 1
		UNION ALL
		SELECT [n] = c.[n] + 1
		FROM c
)
SELECT * FROM c

и join этого с исходной таблицей по полю количество

J.d, во-первых, у вас бесконечная рекурсия, во-вторых, вот вам для сравнения:
set statistics io on;
set statistics time on;

with L0 as (select 0 x union all select 0),
     L1 as (select 0 x from L0 t1, L0 t2),
     L2 as (select 0 x from L1 t1, L1 t2),
     L3 as (select 0 x from L2 t1, L2 t2),
     L4 as (select row_number() over(order by (select 1)) N from L3 t1, L3 t2)
select count(*) from L4;

WITH c AS 
(		SELECT [n] = 1
		UNION ALL
		SELECT [n] = c.[n] + 1
		FROM c
		WHERE [n] < 65536
)
SELECT count(*) FROM c
OPTION (MAXRECURSION 0);

set statistics io on;
set statistics time on;
28 сен 11, 11:33    [11346754]     Ответить | Цитировать Сообщить модератору
 Re: Ради интереса  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
так,
Mnior
...
б) да почти нигде не применимо (ни в каких задачках)
да, - редко, но иногда "эффект применения" просто "выносит"
Запрос с датами
iljy: 23 окт 10, 13:09
1. Проффтыкал/склероз.
2. Всётаки редкость.
3.. Имел ввиду не только на реальных задачах, но и включая "пятничные".
28 сен 11, 11:42    [11346843]     Ответить | Цитировать Сообщить модератору
 Re: Ради интереса  [new]
J.d
Member

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

спасибо я знаю что это бесконечная рекурсия.
предполагалось что её ограничат в соответствии с требованиями задачи.

учитывая

Semen81
Это только ради любопытства.


можно сказать, что предложенный мной вариант нагляднее и проще для понимания неопытными программистам,
нежели Ваш.
28 сен 11, 11:42    [11346846]     Ответить | Цитировать Сообщить модератору
 Re: Ради интереса  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
invm,

DECLARE	@Table TABLE (
       Name	VarChar(20)
      ,[Count]	Int
)INSERT	@Table VALUES ('Иванов',3),('Петров',2),('Сидоров',5)

;WITH Temp AS (
      SELECT	* 
      FROM	@Table T
UNION ALL
      SELECT	 Name
		,[Count] - 1
      FROM	Temp  T
      WHERE	 [Count] > 1
)SELECT	*
FROM	Temp
----------------------------------------------------------------
SELECT	 T.Name
	,V.number + 1	AS number
FROM	     @Table			T
	JOIN master.dbo.spt_values	V ON V.number < [Count]
WHERE	V.[type] = 'P'
28 сен 11, 11:49    [11346905]     Ответить | Цитировать Сообщить модератору
 Re: Ради интереса  [new]
iljy
Member

Откуда:
Сообщений: 8711
J.d
учитывая

Semen81
Это только ради любопытства.


можно сказать, что предложенный мной вариант нагляднее и проще для понимания неопытными программистам,
нежели Ваш.

Это не повод учить неопытных программистов заведомо проигрышным алгоритмам. А этот вопрос обсуждался совсем недавно
https://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=851526&msg=11328917
28 сен 11, 11:53    [11346942]     Ответить | Цитировать Сообщить модератору
 Re: Ради интереса  [new]
Semen81
Member

Откуда:
Сообщений: 160
Спасибо всем огромное!!!! Самообразованность повысилась )))
28 сен 11, 11:55    [11346956]     Ответить | Цитировать Сообщить модератору
 Re: Ради интереса  [new]
J.d
Member

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

ну разве что было пожелание в столбце всегда отображать "1" а не 1,2,3 .. n
28 сен 11, 11:56    [11346967]     Ответить | Цитировать Сообщить модератору
 Re: Ради интереса  [new]
J.d
Member

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

это был не алгоритм, а всего лишь подход.
по сути он такой же, как описанный Вами.

просто впечатление о CTE скорее будет располагать к дальнейшему использованию при виде моей конструкции,
а не наоборот ( как в случае с Вашим примером )
=)
28 сен 11, 11:59    [11347000]     Ответить | Цитировать Сообщить модератору
 Re: Ради интереса  [new]
invm
Member

Откуда: Москва
Сообщений: 9836
Mnior
invm,

DECLARE	@Table TABLE (
       Name	VarChar(20)
      ,[Count]	Int
)INSERT	@Table VALUES ('Иванов',3),('Петров',2),('Сидоров',5)

;WITH Temp AS (
      SELECT	* 
      FROM	@Table T
UNION ALL
      SELECT	 Name
		,[Count] - 1
      FROM	Temp  T
      WHERE	 [Count] > 1
)SELECT	*
FROM	Temp
----------------------------------------------------------------
SELECT	 T.Name
	,V.number + 1	AS number
FROM	     @Table			T
	JOIN master.dbo.spt_values	V ON V.number < [Count]
WHERE	V.[type] = 'P'
И?
28 сен 11, 12:06    [11347050]     Ответить | Цитировать Сообщить модератору
 Re: Ради интереса  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
11328917
iljy
выигрывает примерно в 20 раз.
Вы замеряли на время? (В планах жалкие проценты)
Неужели CTE несоизмеримый тормоз?

И что быстрее на таблице чисел?:
  • APPLY + TOP(Column) { + Row_Number() }
  • JOIN + <

    Тестить на табле с большим количеством строк и большим значением [Count].

    Одно дело обрезать поток (Top), а другое постоянно сравнивать на < (Seek). Но по сути похоже.
    Интересно какой микрокоманд (ASM) круче.
  • 28 сен 11, 12:21    [11347150]     Ответить | Цитировать Сообщить модератору
     Re: Ради интереса  [new]
    Glory
    Member

    Откуда:
    Сообщений: 104751
    Semen81
    Всем привет!!! Интересует решение следующей задачки, причем хотелось бы решить ее не использую цикл, если это возможно, т.к. ее реализовал с применением его. Есть запись в таблице типа:
    Наименование Количество Сумма
    Калькулятор 3 150


    Возможно ли запросом получить на выходе таблицу следующего вида:
    Наименование Количество Цена
    Калькулятор 1 50
    Калькулятор 1 50
    Калькулятор 1 50

    Ради интереса тоже, а как 100 поделится ровно на 3 ? Или сумма результатов деления не должна равняться оригинальной ?
    28 сен 11, 12:25    [11347166]     Ответить | Цитировать Сообщить модератору
     Re: Ради интереса  [new]
    J.d
    Member

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

    в столбце сумма будем использовать тип float
    :D
    28 сен 11, 12:33    [11347246]     Ответить | Цитировать Сообщить модератору
     Re: Ради интереса  [new]
    Glory
    Member

    Откуда:
    Сообщений: 104751
    J.d
    Glory,

    в столбце сумма будем использовать тип float
    :D

    И что же будет в этих столбцах после деления 100 на 3 ? )
    28 сен 11, 12:34    [11347263]     Ответить | Цитировать Сообщить модератору
     Re: Ради интереса  [new]
    J.d
    Member

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

    DECLARE @Table TABLE (NAME VARCHAR(20), [Count] INT, [sum] FLOAT)
    INSERT @Table
    VALUES
      ( 'Иванов',3, 100 ),('Петров', 3, 200),('Сидоров', 4, 300)
    
    
    ;WITH c AS 
    (
        SELECT [n] = MAX(COUNT)
        FROM   @Table
        UNION ALL
        SELECT [n] = c.[n] - 1
        FROM   c
        WHERE  [n] > 0
    ),  c2 AS(
                     SELECT t.name,
    			t.[Count],
                            [subsum] = t.[sum] / t.[Count]
                     FROM   c
                            JOIN @Table t
                                 ON  t.[Count] >= c.[n]
    ) SELECT c2.name, c2.[subsum], c2.[subsum] *  c2.[Count]
      FROM c2
    ORDER BY c2.name
    

    =)
    28 сен 11, 12:42    [11347345]     Ответить | Цитировать Сообщить модератору
    Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
    Все форумы / Microsoft SQL Server Ответить