在SQL Server

时间:2018-03-19 20:45:49

标签: sql-server

我有以下表格的数据:

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中做的事情。

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

3 个答案:

答案 0 :(得分:2)

这是一个计数表是工作的正确工具。我保留一个作为我的系统的视图。它非常快。

<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:tns="http://tempuri.org/" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex" xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsa10="http://www.w3.org/2005/08/addressing" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" name="Calc" targetNamespace="http://tempuri.org/">
<wsdl:types>
<xsd:schema targetNamespace="http://tempuri.org/Imports">
<xsd:import schemaLocation="http://localhost:7510/Calc.svc?xsd=xsd0" namespace="http://tempuri.org/"/>
<xsd:import schemaLocation="http://localhost:7510/Calc.svc?xsd=xsd1" namespace="http://schemas.microsoft.com/2003/10/Serialization/"/>
</xsd:schema>
</wsdl:types>
<wsdl:message name="ICalc_XMLData_InputMessage">
<wsdl:part name="parameters" element="tns:XMLData"/>
</wsdl:message>
<wsdl:message name="ICalc_XMLData_OutputMessage">
<wsdl:part name="parameters" element="tns:XMLDataResponse"/>
</wsdl:message>
<wsdl:message name="ICalc_JSONData_InputMessage">
<wsdl:part name="parameters" element="tns:JSONData"/>
</wsdl:message>
<wsdl:message name="ICalc_JSONData_OutputMessage">
<wsdl:part name="parameters" element="tns:JSONDataResponse"/>
</wsdl:message>
<wsdl:portType name="ICalc">
<wsdl:operation name="XMLData">
<wsdl:input wsaw:Action="http://tempuri.org/ICalc/XMLData" message="tns:ICalc_XMLData_InputMessage"/>
<wsdl:output wsaw:Action="http://tempuri.org/ICalc/XMLDataResponse" message="tns:ICalc_XMLData_OutputMessage"/>
</wsdl:operation>
<wsdl:operation name="JSONData">
<wsdl:input wsaw:Action="http://tempuri.org/ICalc/JSONData" message="tns:ICalc_JSONData_InputMessage"/>
<wsdl:output wsaw:Action="http://tempuri.org/ICalc/JSONDataResponse" message="tns:ICalc_JSONData_OutputMessage"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:service name="Calc"/>
</wsdl:definitions>

现在我们只需要一些示例数据,然后我们就可以加入我们的计数表了。

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

由于您无法创建视图,因此您可以稍微调整此cte以满足您当前的需求并让cte在您的查询中。这样的事情。

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

答案 1 :(得分:1)

也许您可以使用内置的spt_values表格,如果选择Type =&#39; P&#39;,Number会返回0到2047之间的连续数字。 如果列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

答案 2 :(得分:0)

如果没有表示所有日期,并且您只想列出表格中的日期,我认为以下内容会起作用:

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