在T-SQL中返回重复行

时间:2011-01-17 12:20:08

标签: c# sql sql-server tsql

我正在编写一个SQL语句,它将客户交付的详细信息输出到一个漂亮的转发器网格中。但是,基于customers表中的字段(使用整数确定行数),我需要能够生成那些具有完全相同细节的行。

I.E:交付有一行,但根据该客户的customers表中的数字,需要在SQL中多次输出同一行。

有什么想法吗?很抱歉,如果它有点令人困惑,我知道这听起来很愚蠢,但是从正在为该交付生成的SQL'标签',可能需要多个标签。

3 个答案:

答案 0 :(得分:3)

这是一种方法,利用“数字”表,您可以创建并填充从1到n的数字(一次性过程)

SELECT d.*
FROM Delivery d
    JOIN Customer c ON d.CustomerID = c.ID
    JOIN @Numbers n ON c.NumberField >= n.Num

e.g。基本的例子

DECLARE @T1 TABLE (ID INTEGER)
DECLARE @T2 TABLE (ID INTEGER, RowCnt INTEGER)
INSERT @T1 VALUES (1)
INSERT @T1 VALUES (2)
INSERT @T1 VALUES (3)
INSERT @T1 VALUES (4)
INSERT @T2 VALUES (1,1)
INSERT @T2 VALUES (2,2)
INSERT @T2 VALUES (3,4)

DECLARE @Numbers TABLE (Num INTEGER)
INSERT @Numbers VALUES(1)
INSERT @Numbers VALUES(2)
INSERT @Numbers VALUES(3)
INSERT @Numbers VALUES(4)
INSERT @Numbers VALUES(5)

SELECT t1.*
FROM @T1 t1
    JOIN @T2 t2 ON t1.ID = t2.ID
    JOIN @Numbers n ON t2.RowCnt >= n.Num

<强>更新
如果您不想创建物理数字表,则可以(对于数字1-2048)使用这样的spt_values:

SELECT t1.*
FROM @T1 t1
    JOIN @T2 t2 ON t1.ID = t2.ID
    JOIN spt_values n ON t2.RowCnt >= n.Num AND n.type='P'

答案 1 :(得分:3)

AdaTheDev的扩展答案。使用CTE创建数字表。

with Numbers(Num)
as
(
    select 1 as Num
    union all
    select (Num + 1) as Num
    from Numbers
    where Num < 1000
)
select t1.*
from @T1 t1
    join @T2 t2 on t1.ID = t2.ID
    join Numbers n on t2.RowCnt >= n.Num option(maxrecursion 1000)

答案 2 :(得分:0)

我认为这里运作良好的是递归CTE。在我的示例中,我使用一些仅用于演示的示例数据来创建表变量。 DECLARE @RepeatedLevel = 3;及以后的部分是查询本身。

-- Sample table variables are purely for demonstration.
DECLARE @Customer TABLE
(
    ID INT IDENTITY(1,1)
    , Name VARCHAR(25)
)

DECLARE @Delivery TABLE
(
    ID INT IDENTITY(1,1)
    , CustomerID INT
    , DeliveryDate DATE
);

INSERT INTO @Customer
VALUES ('Jeremy'), ('Chris'), ('Sachin'), ('AdaTheDev');

INSERT INTO @Delivery
VALUES (1, '20100602')
    , (2, '20100726')
    , (2, '20110103')
    , (3, '20090401')
    , (3, '20100214')
    , (3, '20100726')
    , (4, '20100713')
    , (4, '20100719')
    , (4, '20100813')
    , (4, '20101028');

DECLARE @RepeatedLevel INT = 3;

WITH DeliverysRepeated AS
(
    SELECT
        Customer.Name
        , Delivery.DeliveryDate
        , 1 AS RecursionLevel
    FROM @Customer Customer
    INNER JOIN @Delivery Delivery
        ON Delivery.CustomerID = Customer.ID

    UNION ALL

    SELECT
        DeliverysRepeated.Name
        , DeliverysRepeated.DeliveryDate
        , DeliverysRepeated.RecursionLevel + 1 AS RecursionLevel
    FROM DeliverysRepeated 
    WHERE DeliverysRepeated.RecursionLevel < @RepeatedLevel
)
SELECT
    DeliverysRepeated.Name
    , DeliverysRepeated.DeliveryDate
FROM DeliverysRepeated
ORDER BY Name, DeliveryDate DESC