SQL将4个查询合并为一个 [英] SQL Merging 4 Queries to one
问题描述
合并以下语句时出现小问题
Im having a slight issue merging the following statements
declare @From DATE
SET @From = '01/01/2014'
declare @To DATE
SET @To = '31/01/2014'
--ISSUED SB
SELECT
COUNT(pm.DateAppIssued) AS Issued,
pm.Lender,
pm.AmountRequested,
p.CaseTypeID
FROM BPS.dbo.tbl_Profile_Mortgage AS pm
INNER JOIN BPS.dbo.tbl_Profile AS p
ON pm.FK_ProfileId = p.Id
WHERE CaseTypeID = 2
AND (CONVERT(DATE,DateAppIssued, 103)
Between CONVERT(DATE,@From,103) and CONVERT(DATE,@To,103))
And Lender > ''
GROUP BY pm.Lender,p.CaseTypeID,pm.AmountRequested;
--Paased
SELECT
COUNT(pm.DatePassed) AS Passed,
pm.Lender,
pm.AmountRequested,
p.CaseTypeID
FROM BPS.dbo.tbl_Profile_Mortgage AS pm
INNER JOIN BPS.dbo.tbl_Profile AS p
ON pm.FK_ProfileId = p.Id
WHERE CaseTypeID = 2
AND (CONVERT(DATE,DatePassed, 103)
Between CONVERT(DATE,@From,103) and CONVERT(DATE,@To,103))
And Lender > ''
GROUP BY pm.Lender,p.CaseTypeID,pm.AmountRequested;
--Received
SELECT
COUNT(pm.DateAppRcvd) AS Received,
pm.Lender,
pm.AmountRequested,
p.CaseTypeID
FROM BPS.dbo.tbl_Profile_Mortgage AS pm
INNER JOIN BPS.dbo.tbl_Profile AS p
ON pm.FK_ProfileId = p.Id
WHERE CaseTypeID = 2
AND (CONVERT(DATE,DateAppRcvd, 103)
Between CONVERT(DATE,@From,103) and CONVERT(DATE,@To,103))
And Lender > ''
GROUP BY pm.Lender,p.CaseTypeID,pm.AmountRequested;
--Offered
SELECT
COUNT(pm.DateOffered) AS Offered,
pm.Lender,
pm.AmountRequested,
p.CaseTypeID
FROM BPS.dbo.tbl_Profile_Mortgage AS pm
INNER JOIN BPS.dbo.tbl_Profile AS p
ON pm.FK_ProfileId = p.Id
WHERE CaseTypeID = 2
AND (CONVERT(DATE,DateOffered, 103)
Between CONVERT(DATE,@From,103) and CONVERT(DATE,@To,103))
And Lender > ''
GROUP BY pm.Lender,p.CaseTypeID,pm.AmountRequested;
理想情况下,我希望这些查询的结果显示如下
Ideally I would like the result of theses query's to show as follows
已发出,已通过,已提供,已接收, 在一桌之中
Issued, Passed , Offered, Received, All in one table
对此的任何帮助将不胜感激 谢谢 生锈
Any Help on this would be greatly appreciated Thanks Rusty
推荐答案
在这种情况下,我相当确定可以在不使用任何CASE
语句的情况下编写查询,实际上是:
I'm fairly certain in this case the query can be written without the use of any CASE
statements, actually:
DECLARE @From DATE = '20140101'
declare @To DATE = '20140201'
SELECT Mortgage.lender, Mortgage.amountRequested, Profile.caseTypeId,
COUNT(Issue.issued) as issued,
COUNT(Pass.passed) as passed,
COUNT(Receive.received) as received,
COUNT(Offer.offered) as offered
FROM BPS.dbo.tbl_Profile_Mortgage as Mortgage
JOIN BPS.dbo.tbl_Profile as Profile
ON Mortgage.fk_profileId = Profile.id
AND Profile.caseTypeId = 2
LEFT JOIN (VALUES (1, @From, @To)) Issue(issued, rangeFrom, rangeTo)
ON Mortgage.DateAppIssued >= Issue.rangeFrom
AND Mortgage.DateAppIssued < Issue.rangeTo
LEFT JOIN (VALUES (2, @From, @To)) Pass(passed, rangeFrom, rangeTo)
ON Mortgage.DatePassed >= Pass.rangeFrom
AND Mortgage.DatePassed < Pass.rangeTo
LEFT JOIN (VALUES (3, @From, @To)) Receive(received, rangeFrom, rangeTo)
ON Mortgage.DateAppRcvd >= Receive.rangeFrom
AND Mortgage.DateAppRcvd < Receive.rangeTo
LEFT JOIN (VALUES (4, @From, @To)) Offer(offered, rangeFrom, rangeTo)
ON Mortgage.DateOffered >= Offer.rangeFrom
AND Mortgage.DateOffered < Offer.rangeTo
WHERE Mortgage.lender > ''
AND (Issue.issued IS NOT NULL
OR Pass.passed IS NOT NULL
OR Receive.received IS NOT NULL
OR Offer.offered IS NOT NULL)
GROUP BY Mortgage.lender, Mortgage.amountRequested, Profile.caseTypeId
(未经测试,因为我缺少提供的数据集).
(not tested, as I lack a provided data set).
...好吧,一些解释是有条理的,因为其中有些是不直观的.
... Okay, some explanations are in order, because some of this is slightly non-intuitive.
First off, read this blog entry for tips about dealing with date/time/timestamp ranges (interestingly, this also applies to all other non-integral types). This is why I modified the @To
date - so the range could be safely queried without needing to convert types (and thus ignore indices). I've also made sure to choose a safe format - depending on how you're calling this query, this is a non issue (ie, parameterized queries taking an actual Date
type are essentially format-less).
......
COUNT(Issue.issued) as issued,
......
LEFT JOIN (VALUES (1, @From, @To)) Issue(issued, rangeFrom, rangeTo)
ON Mortgage.DateAppIssued >= Issue.rangeFrom
AND Mortgage.DateAppIssued < Issue.rangeTo
.......
COUNT(*)
和COUNT(<expression>)
有什么区别?如果<expression>
计算为null
,则将其忽略.因此LEFT JOIN
s;如果抵押贷款条目不在该列的给定日期范围内,则虚拟表不会附加,也没有可计数的列.不幸的是,我不确定虚拟表,LEFT JOIN
和COUNT()
之间的相互作用在优化程序中会如何出现-联接应该能够使用索引,但是我不知道它是否足够智能也可以将其用于COUNT()
.
What's the difference between COUNT(*)
and COUNT(<expression>)
? If <expression>
evaluates to null
, it's ignored. Hence the LEFT JOIN
s; if the entry for the mortgage isn't in the given date range for the column, the dummy table doesn't attach, and there's no column to count. Unfortunately, I'm not sure how the interplay between the dummy table, LEFT JOIN
, and COUNT()
here will appear to the optimizer - the joins should be able to use indices, but I don't know if it's smart enough to be able to use that for the COUNT()
here too....
(Issue.issued IS NOT NULL
OR Pass.passed IS NOT NULL
OR Receive.received IS NOT NULL
OR Offer.offered IS NOT NULL)
这实际上是在告诉它忽略没有至少一个列的行.在任何情况下都不会计数"(嗯,它们很可能具有0
)-没有要考虑的功能数据-但是它们会会显示在结果中,从而可能不是您想要的.我不确定优化器是否足够聪明,可以使用它来限制它对哪些行进行操作-也就是说,将JOIN
条件转换为一种限制各种日期列的方式,就像它们在WHERE
中一样子句也一样.如果查询运行缓慢,请尝试将日期限制添加到WHERE
子句中,看看是否有帮助.
This is essentially telling it to ignore rows that don't have at least one of the columns. They wouldn't be "counted" in any case (well, they'd likely have 0
) - there's no data for the function to consider - but they would show up in the results, which probably isn't what you want. I'm not sure if the optimizer is smart enough to use this to restrict which rows it operates over - that is, turn the JOIN
conditions into a way to restrict the various date columns, as if they were in the WHERE
clause too. If the query runs slow, try adding the date restrictions to the WHERE
clause and see if it helps.
这篇关于SQL将4个查询合并为一个的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!