我正在教自己MS-SQL,我正在尝试找到不同的方法来查找2012年按区域分组的2012年付费和未付索赔的数量。如果返回日期,如果返回的日期为空,则索赔未付,则支付索赔。
我会附上我运行的代码,但我不确定是否有更好的方法可以做到。
感谢。
以下是代码:
SET dateformat ymd;
CREATE TABLE Claims
(
ClaimID INT,
SubID INT,
[Claim Date] DATETIME
);
CREATE TABLE Phoneship
(
ClaimID INT,
[Shipping Number] INT,
[Claim Date] DATETIME,
[Ship Date] DATETIME,
[Returned Date] DATETIME
);
CREATE TABLE Enrollment
(
SubID INT,
Enrollment_Date DATETIME,
Channel NVARCHAR(255),
Region NVARCHAR(255),
Status FLOAT,
Drop_Date DATETIME
);
INSERT INTO [Phoneship]
([ClaimID],
[Shipping Number],
[Claim Date],
[Ship Date],
[Returned Date])
VALUES (102,
201,
'2011-10-13 00:00:00',
'2011-10-14 00:00:00',
NULL);
INSERT INTO [Phoneship]
([ClaimID],
[Shipping Number],
[Claim Date],
[Ship Date],
[Returned Date])
VALUES (103,
202,
'2011-11-02 00:00:00',
'2011-11-03 00:00:00',
'2011-11-20 00:00:00');
INSERT INTO [Phoneship]
([ClaimID],
[Shipping Number],
[Claim Date],
[Ship Date],
[Returned Date])
VALUES (103,
203,
'2011-11-02 00:00:00',
'2011-11-22 00:00:00',
NULL);
INSERT INTO [Phoneship]
([ClaimID],
[Shipping Number],
[Claim Date],
[Ship Date],
[Returned Date])
VALUES (105,
204,
'2012-01-16 00:00:00',
'2012-01-17 00:00:00',
NULL);
INSERT INTO [Phoneship]
([ClaimID],
[Shipping Number],
[Claim Date],
[Ship Date],
[Returned Date])
VALUES (106,
205,
'2012-02-15 00:00:00',
'2012-02-16 00:00:00',
'2012-02-26 00:00:00');
INSERT INTO [Phoneship]
([ClaimID],
[Shipping Number],
[Claim Date],
[Ship Date],
[Returned Date])
VALUES (106,
206,
'2012-02-15 00:00:00',
'2012-02-27 00:00:00',
'2012-03-06 00:00:00');
INSERT INTO [Phoneship]
([ClaimID],
[Shipping Number],
[Claim Date],
[Ship Date],
[Returned Date])
VALUES (107,
207,
'2012-03-12 00:00:00',
'2012-03-13 00:00:00',
NULL);
INSERT INTO [Phoneship]
([ClaimID],
[Shipping Number],
[Claim Date],
[Ship Date],
[Returned Date])
VALUES (108,
208,
'2012-05-11 00:00:00',
'2012-05-12 00:00:00',
NULL);
INSERT INTO [Phoneship]
([ClaimID],
[Shipping Number],
[Claim Date],
[Ship Date],
[Returned Date])
VALUES (109,
209,
'2012-05-13 00:00:00',
'2012-05-14 00:00:00',
'2012-05-28 00:00:00');
INSERT INTO [Phoneship]
([ClaimID],
[Shipping Number],
[Claim Date],
[Ship Date],
[Returned Date])
VALUES (109,
210,
'2012-05-13 00:00:00',
'2012-05-30 00:00:00',
NULL);
INSERT INTO [Claims]
([ClaimID],
[SubID],
[Claim Date])
VALUES (101,
12345678,
'2011-03-06 00:00:00');
INSERT INTO [Claims]
([ClaimID],
[SubID],
[Claim Date])
VALUES (102,
12347190,
'2011-10-13 00:00:00');
INSERT INTO [Claims]
([ClaimID],
[SubID],
[Claim Date])
VALUES (103,
12348723,
'2011-11-02 00:00:00');
INSERT INTO [Claims]
([ClaimID],
[SubID],
[Claim Date])
VALUES (104,
12349745,
'2011-11-09 00:00:00');
INSERT INTO [Claims]
([ClaimID],
[SubID],
[Claim Date])
VALUES (105,
12347190,
'2012-01-16 00:00:00');
INSERT INTO [Claims]
([ClaimID],
[SubID],
[Claim Date])
VALUES (106,
12349234,
'2012-02-15 00:00:00');
INSERT INTO [Claims]
([ClaimID],
[SubID],
[Claim Date])
VALUES (107,
12350767,
'2012-03-12 00:00:00');
INSERT INTO [Claims]
([ClaimID],
[SubID],
[Claim Date])
VALUES (108,
12350256,
'2012-05-11 00:00:00');
INSERT INTO [Claims]
([ClaimID],
[SubID],
[Claim Date])
VALUES (109,
12347701,
'2012-05-13 00:00:00');
INSERT INTO [Claims]
([ClaimID],
[SubID],
[Claim Date])
VALUES (110,
12350256,
'2012-05-15 00:00:00');
INSERT INTO [Claims]
([ClaimID],
[SubID],
[Claim Date])
VALUES (111,
12350767,
'2012-06-30 00:00:00');
INSERT INTO [Enrollment]
([SubID],
[Enrollment_Date],
[Channel],
[Region],
[Status],
[Drop_Date])
VALUES (12345678,
'2011-01-05 00:00:00',
'Retail',
'Southeast',
1,
NULL);
INSERT INTO [Enrollment]
([SubID],
[Enrollment_Date],
[Channel],
[Region],
[Status],
[Drop_Date])
VALUES (12346178,
'2011-03-13 00:00:00',
'Indirect Dealers',
'West',
1,
NULL);
INSERT INTO [Enrollment]
([SubID],
[Enrollment_Date],
[Channel],
[Region],
[Status],
[Drop_Date])
VALUES (12346679,
'2011-05-19 00:00:00',
'Indirect Dealers',
'Southeast',
0,
'2012-03-15 00:00:00');
INSERT INTO [Enrollment]
([SubID],
[Enrollment_Date],
[Channel],
[Region],
[Status],
[Drop_Date])
VALUES (12347190,
'2011-07-25 00:00:00',
'Retail',
'Northeast',
0,
'2012-05-21 00:00:00');
INSERT INTO [Enrollment]
([SubID],
[Enrollment_Date],
[Channel],
[Region],
[Status],
[Drop_Date])
VALUES (12347701,
'2011-08-14 00:00:00',
'Indirect Dealers',
'West',
1,
NULL);
INSERT INTO [Enrollment]
([SubID],
[Enrollment_Date],
[Channel],
[Region],
[Status],
[Drop_Date])
VALUES (12348212,
'2011-09-30 00:00:00',
'Retail',
'West',
1,
NULL);
INSERT INTO [Enrollment]
([SubID],
[Enrollment_Date],
[Channel],
[Region],
[Status],
[Drop_Date])
VALUES (12348723,
'2011-10-20 00:00:00',
'Retail',
'Southeast',
1,
NULL);
INSERT INTO [Enrollment]
([SubID],
[Enrollment_Date],
[Channel],
[Region],
[Status],
[Drop_Date])
VALUES (12349234,
'2012-01-06 00:00:00',
'Indirect Dealers',
'West',
0,
'2012-02-14 00:00:00');
INSERT INTO [Enrollment]
([SubID],
[Enrollment_Date],
[Channel],
[Region],
[Status],
[Drop_Date])
VALUES (12349745,
'2012-01-26 00:00:00',
'Retail',
'Northeast',
0,
'2012-04-15 00:00:00');
INSERT INTO [Enrollment]
([SubID],
[Enrollment_Date],
[Channel],
[Region],
[Status],
[Drop_Date])
VALUES (12350256,
'2012-02-11 00:00:00',
'Retail',
'Southeast',
1,
NULL);
INSERT INTO [Enrollment]
([SubID],
[Enrollment_Date],
[Channel],
[Region],
[Status],
[Drop_Date])
VALUES (12350767,
'2012-03-02 00:00:00',
'Indirect Dealers',
'West',
1,
NULL);
INSERT INTO [Enrollment]
([SubID],
[Enrollment_Date],
[Channel],
[Region],
[Status],
[Drop_Date])
VALUES (12351278,
'2012-04-18 00:00:00',
'Retail',
'Midwest',
1,
NULL);
INSERT INTO [Enrollment]
([SubID],
[Enrollment_Date],
[Channel],
[Region],
[Status],
[Drop_Date])
VALUES (12351789,
'2012-05-08 00:00:00',
'Indirect Dealers',
'West',
0,
'2012-07-04 00:00:00');
INSERT INTO [Enrollment]
([SubID],
[Enrollment_Date],
[Channel],
[Region],
[Status],
[Drop_Date])
VALUES (12352300,
'2012-06-24 00:00:00',
'Retail',
'Midwest',
1,
NULL);
INSERT INTO [Enrollment]
([SubID],
[Enrollment_Date],
[Channel],
[Region],
[Status],
[Drop_Date])
VALUES (12352811,
'2012-06-25 00:00:00',
'Retail',
'Southeast',
1,
NULL);
和Query1
SELECT Count(ClaimID) AS 'Paid Claim',
(SELECT Count(ClaimID)
FROM dbo.phoneship
WHERE [returned date] IS NOT NULL) AS 'Unpaid Claim'
FROM dbo.Phoneship
WHERE [Returned Date] IS NULL
GROUP BY claimid
QUERY2
SELECT Count(*) AS 'Paid Claims',
(SELECT Count(*)
FROM dbo.Phoneship
WHERE [Returned Date] IS NOT NULL) AS 'Unpaid Claims'
FROM dbo.Phoneship
WHERE [Returned Date] IS NULL;
QUERY3
Select Distinct(C.[Shipping Number]), Count(C.ClaimID) AS 'COUNT ClaimID',
A.Region, A.SubID
From dbo.HSEnrollment A
Inner Join dbo.Claims B On A.SubId = B.SubId
Inner Join dbo.Phoneship C On B.ClaimID = C.ClaimID
Where C.[Returned Date] IS NULL
Group By A.Region, A.Subid, C.ClaimID, C.[Shipping Number] Order By A.Region
答案 0 :(得分:1)
您需要将所有表连接在一起才能获得该区域。此版本假定每个声明的电话记录最多:
SELECT e.region, count(*) as numclaims,
sum(case when ps.ReturnedDate is not null then 1 else 0 end) AS 'Paid Claim',
sum(case when ps.ReturnedDate is null then 1 else 0 end) AS 'Unpaid Claim'
FROM claims c join
enrollment e
on c.sub_id = e.sub_id left outer join
Phoneship ps
on ps.claimid = c.claimdid
WHERE [Returned Date] IS NULL
GROUP BY e.region
如果有多个,则计数将被关闭,因为每个电话将被计算而不是每个声明。要解决此问题,请将两个总和更改为:
count(distinct case when ps.ReturnedDate is not null then c.claimid end)
count(distinct case when ps.ReturnedDate is null then c.claimid end)
答案 1 :(得分:1)
很难回答这个问题,因为我看到了你在问什么,但是还有其他一些小问题导致你的查询困难。
我的回答
所以,在这里回答你的问题的核心是我会做什么,当且仅当我正确地解释你的表结构时(更多的是继续)。
我没有包括索赔的数量,因为这会甩掉数字。我已经包含了两个查询,即最终查询和细分查询。对于总和(因为你正在学习),我使用WITH ROLLUP来获得每个分组列的总和。
SELECT
e.Region,
paid = SUM(CASE WHEN p.[Returned Date] IS NULL THEN 1 ELSE 0 END),
unpaid = SUM(CASE WHEN p.[Returned Date] IS NULL THEN 0 ELSE 1 END)
FROM claims c
INNER JOIN enrollment e
ON e.SubID = c.SubID
INNER JOIN phoneship p
ON p.ClaimID = c.ClaimID
GROUP BY e.Region
WITH ROLLUP
分解
这是使用内部虚拟表的子选择的分解查询(结果表 - 结果集等...)。我故意这样做是为了表明观点。
SELECT
x.Region,
-- if the Returned Date is null then add 1, otherwise add 0
paid = SUM(CASE WHEN x.ReturnedDate IS NULL THEN 1 ELSE 0 END),
-- if the Returned Date is null then add 0, otherwise add 1
unpaid = SUM(CASE WHEN x.ReturnedDate IS NULL THEN 0 ELSE 1 END)
FROM
(
-- Run this inner query to see what data you are actually working with
-- for your grouping/sums
SELECT
c.ClaimID,
c.SubID,
E = '#', -- This is just a separator
e_SubID = e.SubID, -- This is equivalent to saying e.SubID AS e_SubID
e.Region,
P = '#', -- This is just a separator
p_ClaimID = p.ClaimID,
ShippingNo = p.[Shipping Number], -- Getting rid of those nasty spaces
ReturnedDate = p.[Returned Date]
FROM claims c
INNER JOIN enrollment e
ON e.SubID = c.SubID
-- Initially this was a LEFT JOIN but you are missing Claims in your
-- Phoneship table which will produce bogus results, therefore the
-- INNER JOIN will filter out any rows that don't match
INNER JOIN phoneship p
ON p.ClaimID = c.ClaimID
) as x
GROUP BY x.Region
WITH ROLLUP
如果可以,尽可能避免使用Sub Selects。它们对性能不是很好,但当然有时候你无法避免它。
您的表结构/关系是执行此查询时遇到困难的根本原因。在查看结构后,我发现你正在复制数据(这是一个不可拒绝),而你在将细节全部拉入一个不错的查询时遇到了麻烦。
我看到的问题领域(以及一些友好的建议)
您将Claims表中的ClaimDate列复制到PhoneShip表。我不确定它们是否有不同的含义,但如果它是重复的 - 请避免这种情况。
可能应删除声明表中的SubID。如果将ClaimID作为Foreign Key(FK)放入注册表中会更好。
为Phoneship表提供自己的Primary Key(PK) - 它易于使用,除了ClaimID和ShippingNumber的组合外,每行都是唯一的。查看Table Relationships和Unique Constraints。
我有点不确定如何使用NULL作为是否支付或未付款的良好指标。只有设计者才会知道空字段意味着付费。为此目的最好使用位字段,默认值为零并标记为NOT NULL - 这样它永远不会为空。毕竟这将为您省去编写案例陈述的麻烦,您可以直接使用该位作为您的总和Ex:SUM(x.Paid)。此外,如果出于各种原因而不打算将列错误地标记为NULL。
考虑完全从“注册”表中提取“渠道”和“地区”列。使用Integer PK将它们放在自己的表中。您可以使用ChannelID和RegionID在任何需要的地方引用PK。这样,如果名称需要更改,您将不必担心数据完整性问题(UPDATE表SET NameCol ='a'WHERE NameCol ='b' - 这可能会导致意外的重命名灾难。)
将RegionID和ChannelID放入Claims表中。如果您按照上面的步骤2(在注册表中有一个ClaimID FK),现在您在注册表中不需要它。
恭喜你主动学习这些东西。这是非常宝贵的知识(除非你上大学,在这种情况下它值得大约50K或更差......学生贷款......叹息......)。
答案 2 :(得分:0)
试试这个
SELECT e.Region, COUNT(c.SubID) TotalClaims, COUNT(p.[returned date]) UnpaidClaims, COUNT(c.SubID)-COUNT(p.[returned date]) PaidClaims
FROM
Claims c
INNER JOIN enrollment e ON c.SubID = e.SubID
INNER JOIN phoneship p ON p.ClaimID = c.ClaimID
GROUP BY e.Region