代码之家  ›  专栏  ›  技术社区  ›  Maury Markowitz

在SQL Server中按(num)行划分一行

  •  3
  • Maury Markowitz  · 技术社区  · 8 年前

    我有以下表格的数据:

    ID         name     date    count
    ---------------------------------
    1           A     1/1/2015    3
    2           B     1/4/2015    2
    3           C     1/6/2015    4
    4           D     1/10/2015   2
    

    我想把它变成。。。

    1 A 1/1/2015
    1 A 1/2/2015
    1 A 1/3/2015
    2 B 1/4/2015
    2 B 1/5/2015
    3 C 1/6/2015
    ...
    

    我相信使用分区查询是可能的,但我在理解 examples I find on the MS page 。我需要使用 ROW_NUMBER 在里面 DATEADD ,但我不知道如何让它返回正确的行数,例如第一种情况为3。这个 TerritoryName 示例似乎很接近。。。

    在最坏的情况下,我可以在VBA代码中实现这一点,我也知道使用充满日期的表的解决方案,但我认为如果可能的话,我应该知道如何在SELECT中实现这一点。

    更新时间: 我不允许更改原始数据库中的任何内容(许可问题)。我可以用#废话,但如果可能的话,我宁愿避免这样。

    3 回复  |  直到 8 年前
        1
  •  2
  •   Sean Lange    8 年前

    在这里,理货表是作业的正确工具。我在我的系统上保留一个视图。速度快得离谱。

    create View [dbo].[cteTally] as
    
    WITH
        E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
        E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
        E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
        cteTally(N) AS 
        (
            SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
        )
    select N from cteTally
    GO
    

    现在我们只需要一些样本数据,然后就可以加入我们的理货表。

    set dateformat mdy --you really should use ANSI standard YYYYMMDD
    
    insert @Something values
    (1, 'A', '1/1/2015', 3)
    ,(2, 'B', '1/4/2015', 2)
    ,(3, 'C', '1/6/2015', 4)
    ,(4, 'D', '1/10/2015', 2)
    
    select s.*
        , DATEADD(day, t.N - 1, s.SomeDate)
    from @Something s
    join cteTally t on t.N <= s.SomeCount
    

    由于您无法创建视图,因此也可以将此cte缩小一点,以满足您当前的需要,并将cte包含在您的查询中。像这样的。

    WITH
        E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
        cteTally(N) AS 
        (
            SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E1
        )
    select s.*
        , DATEADD(day, t.N - 1, s.SomeDate)
    from @Something s
    join cteTally t on t.N <= s.SomeCount
    
        2
  •  1
  •   Ivan Golović    8 年前

    也许您可以使用内置 spt_values 表,如果选择打开 Type ='P', Number 返回0到2047之间的连续数字。 If列 count 包含天数查询的可靠值可以是:

    select t.id, t.name, dateadd(d, numbers.Number, t.date) as date
    from t
    join master..spt_values as numbers
    on numbers.Type = 'P'
    and numbers.Number < t.count
    

    小提琴: http://sqlfiddle.com/#!18/62aee/2

        3
  •  0
  •   Katerine459    8 年前

    如果不是所有日期都表示出来,并且您只想列出表中的日期,那么我认为以下类似的方法可以奏效:

    SELECT ranknum, itemname, itemdate
    FROM (SELECT RANK() OVER(PARTITION BY t.itemdate ORDER BY allitems.itemname) ranknum
         , t.id
         , allitems.itemname
         , t.itemdate
         FROM (SELECT DISTINCT itemname FROM tablename) allitems 
             LEFT JOIN tablename t ON allitems.itemname = t.itemname) ranked
    WHERE id IS NOT NULL
    ORDER BY ranknum, itemdate