在一组日期中迭代商店

时间:2013-12-13 12:03:12

标签: sql sql-server sql-server-2008-r2

早上好,

我正在寻找解决以下问题的有效方法: (请注意,我已经简化并更改了实际问题;但是这不应该反映我正在寻找的结果)

基本上,如果我想确定特定公司拥有的每个Store的交易数量,按日期分组,我必须运行以下查询:

Select 
date_of_transaction 
,store
,COUNT(*)
from transactions t1
group by date_of_transaction,store
order by date_of_transaction

但是,此查询还不够,因为它不会返回事务数等于“0”的storesdates

例如,如果store A1/Oct/2012没有提交任何交易,则我的结果集中将丢失ROW。

这就是为什么,我想在过去一年的所有365天内强制执行,然后为每个Store显示每个Date。 换句话说,如果公司拥有3家商店,即使交易次数为“0”,我每年的每一天都需要3条记录:

Date        Store      Number
1/1/2012    A          1
1/1/2012    B          0
1/1/2012    C          3
2/1/2012    A          1
2/1/2012    B          2
2/1/2012    C          0
3/1/2012    A          1
3/1/2012    B          0
3/1/2012    C          0

我有一个日历表,我已经习惯'联合'商店并强行进入,但它必须是更好的方法。

此致 基里尔

2 个答案:

答案 0 :(得分:1)

像这样的东西,应该做你想要的(你需要根据你的日历和存储表来查询,获取输出中的所有日期和所有商店,然后LEFT JOIN事务表):

SELECT Calendar.Date, Stores.Store, COUNT(T1.transaction_id) AS Number
FROM Calendar, Stores
LEFT JOIN Transactions T1 ON T1.date_of_transaction = Calendar.date 
    AND T1.store = Stores.store
GROUP BY Calendar.Date, Stores.Store

答案 1 :(得分:1)

为什么不使用公用表表达式来计算不同的存储和日期。

以下是包含上述数据的测试表。

--
-- My database
--

-- Play in temp
use tempdb;
go

-- Create a table
CREATE TABLE my_transactions
(
  my_id INT identity(1, 1) primary key,
  my_date DATETIME,
  my_store CHAR(1),
  my_sale MONEY
);

-- Insert some data
INSERT INTO my_transactions (my_date, my_store, my_sale) 
VALUES
('1/1/2012', 'A', 100),
('1/1/2012', 'C', 100),
('1/1/2012', 'C', 100),
('1/1/2012', 'C', 100),
('2/1/2012', 'A', 200),
('2/1/2012', 'B', 200),
('2/1/2012', 'B', 200),
('3/1/2012', 'A', 300);

-- Show the data
SELECT * FROM my_transactions;

enter image description here

我将使用计数表概念来创建月份开始日期,存储和创建报告。

--
-- My report query
--
;
WITH cteMonths (my_number, my_date) AS 
(
    SELECT
        ROW_NUMBER() OVER(ORDER BY a.name) AS my_number,
        DATEADD(M, ROW_NUMBER() OVER(ORDER BY a.name) - 1, '2012-01-01') as my_date
    FROM 
        sys.objects a 
    CROSS JOIN 
        sys.objects b
),
cteStores (my_store) as
(
  SELECT DISTINCT my_store FROM my_transactions
)
SELECT 
    MS.my_date,
    MS.my_store,
    COUNT(T.my_id) as my_total
FROM 
    ( SELECT * FROM cteMonths CROSS JOIN cteStores WHERE my_number < 4 ) MS
LEFT JOIN
    my_transactions AS T ON MS.my_date = T.my_date and MS.my_store = T.my_store
GROUP BY
    MS.my_date,
    MS.my_store
ORDER BY
    MS.my_date,
    MS.my_store
GO

enter image description here