假设我有2张桌子
第一个是“订单”
Select * from Orders
给我这个结果。
Order_ID Date_Start Date_End Order_Name
2059 2020-11-13 00:00:00.000 2020-11-14 00:00:00.000 order1
2060 2020-12-12 00:00:00.000 2020-12-22 00:00:00.000 order2
第二张桌子说它是“日期”
这是“日期”表的理想结果。我需要为每个订单ID在该表的两个日期之间插入日期。
Date Type1 Type2 Type3 Type4 Type5 Order_ID
2020-11-13 00:00:00.000 NULL NULL NULL NULL NULL 2059
2020-11-14 00:00:00.000 NULL NULL NULL NULL NULL 2059
我希望现在可以更清楚了。
答案 0 :(得分:2)
使用OVER / PARTITION,然后使用dateadd(),实际上非常简单。
首先,我们需要在最终记录列表中获取任意数量的记录。为此,请选择至少具有所需行数的任何表。可以是员工表,客户,订单等。对于您的示例,只要有14天。由此,只要创建一个临时结果集,只要表格中有这么多记录,就可以简单地将数字1遍历任何数字... 10、14、127,任何数字。
现在,按顺序进行分区是技巧的一部分。您不能按常量进行分区,但是可以基于方程式进行分区。因此,选择任何表的“ ID”列并乘以0总是得到0。因此,您的分区将对等值等于0的所有值进行分组...棘手的...所以现在,所有记录都归入这一组,并在该组内分配一个行号。通过“ TOP 14”结束这一工作,您将获得14条记录以开始您的列表基础。
SELECT top 10
ROW_NUMBER() OVER(PARTITION BY SomeTableID * 0 order by SomeTableID * 0) AS "MyRow"
FROM
SomeTable
所以现在,我有一个结果集,其中包含10行,其值从1到10。
现在,让我们建立日期。只要您是连续构建的(例如每天,每月,每年或任何模式),就以一个日期作为基准并继续添加。在下面的示例中,我使用的是当前日期,并且继续添加1个月,但是同样,您可以执行数天,数周的操作。
select
dateadd( month, Counter.MyRow, convert( date, getdate() )) ListOfDates
from
( SELECT top 10 ROW_NUMBER()
OVER(PARTITION BY SomeTableID * 0 order by SomeTableID * 0) AS "MyRow"
FROM SomeTable ) Counter
因此,在上面的示例中,它将从今天开始返回10行并生成
2020-11-20
2020-12-20
2021-01-20
...
2021-08-20
跟进。
您的查询失败,因为您正在显式连接字符串以构建命令...错误技术。您应该参数化您的查询。构建一个SQL Command对象,添加参数,然后调用您的填充。
var sqlcmd = new SqlCommand("", con);
sqlcmd.CommandText =
@"WITH theDates AS
(
SELECT @parmStartDate as theDate
UNION ALL
SELECT DATEADD(day, 1, theDate)
FROM theDates
WHERE DATEADD(day, 1, theDate) <= @parmEndDate
)
SELECT theDate
FROM theDates
OPTION(MAXRECURSION 0)";
sqlcmd.Parameters.AddWithValue("parmStartDate", dataGridView.CurrentRow.Cells[2] );
sqlcmd.Parameters.AddWithValue("parmEndDate", dataGridView.CurrentRow.Cells[3] );
var ds = new DataSet();
var dtbl2 = new DataTable();
// pass the pre-formatted and parameterized query command to the SQL Data Adapter
var sda2 = new SqlDataAdapter(sqlcmd);
答案 1 :(得分:1)
以下是一些用于构建动态日期范围表的sql。在联接 /和/ 联接表节* /
之后,您需要根据需要在/ *列中自定义它。
/*
script to build table with dynamic columns
*/
DROP TABLE IF EXISTS #tempDateRange
DROP TABLE IF EXISTS #dateRangeTable
DECLARE @StartDate datetime = DATEADD(DAY, -14, GETDATE()),
@EndDate datetime = GETDATE()
/*
Generate date range table
*/
SELECT DATEADD(DAY, nbr - 1, @StartDate) AS [Date],
UPPER(LEFT(DATENAME(mm, DATEADD(DAY, nbr - 1, @StartDate)), 3)) AS [MonthShort],
MONTH( DATEADD(DAY, nbr - 1, @StartDate)) AS [Month],
YEAR(DATEADD(DAY, nbr - 1, @StartDate)) AS [Year],
CONCAT(UPPER(LEFT(DATENAME(mm, DATEADD(DAY, nbr - 1, @StartDate)), 3)), '-', YEAR(DATEADD(DAY, nbr - 1, @StartDate))) AS MonthYear
INTO #tempDateRange
FROM ( SELECT TOP(DATEDIFF(DAY, @StartDate, @EndDate)) ones.n + 10*tens.n + 100*hundreds.n + 1000*thousands.n AS Nbr
FROM (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) ones(n),
(VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) tens(n),
(VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) hundreds(n),
(VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) thousands(n)
WHERE ones.n + 10*tens.n + 100*hundreds.n + 1000*thousands.n BETWEEN 1 AND DATEDIFF(DAY, @StartDate, @EndDate)
ORDER BY 1
) nbrs
WHERE nbr - 1 <= DATEDIFF(DAY, @StartDate, @EndDate)
/*
Generate columns for date range
*/
DECLARE
@columns NVARCHAR(MAX) = ''
SELECT @columns+=QUOTENAME(convert(nvarchar(10), Date, 120)) + ' NVARCHAR(10),'
FROM (
SELECT DISTINCT Date, [Month], [Year] FROM #tempDateRange
) x
ORDER BY x.[Year], x.[Month]
SET @columns = LEFT(@columns, LEN(@columns) - 1);
DECLARE @sql NVARCHAR(MAX) = ''
SET @sql = '
INSERT #dateRangeTable
SELECT *
FROM (
SELECT a.TestData AS Data, /* replace with your column after join */
convert(nvarchar(10), Date, 120) AS [Date]
FROM #tempDateRange [date]
/* Join your table */
LEFT JOIN (
SELECT ''start test'' AS TestData, CAST('''+CONVERT(NVARCHAR, @StartDate)+''' AS DATE) AS TargetDate
UNION
SELECT ''end test'' AS TestData, CAST('''+CONVERT(NVARCHAR, DATEADD(DAY, -1, @EndDate))+''' AS DATE) AS TargetDate
) AS a ON CAST(a.TargetDate AS DATE) = CAST(date.[date] AS DATE)
WHERE [date].[Date] BETWEEN CAST('''+CONVERT(NVARCHAR, @StartDate)+''' AS DATE) AND CAST('''+CONVERT(NVARCHAR, @EndDate)+''' AS DATE)
) o
PIVOT(
MAX(Data)
FOR [Date] IN ('+ REPLACE(@columns, 'NVARCHAR(10)', '') +')
) AS pivot_table;
'
SET @sql = N'
DROP TABLE IF EXISTS #dateRangeTable
CREATE TABLE #dateRangeTable('+@columns+')
' +
@sql
+ N'
SELECT * FROM #dateRangeTable
DROP TABLE IF EXISTS #dateRangeTable
'
PRINT (@sql)
--EXECUTE sp_executesql @sql