我正在尝试创建一个SELECT来从几个表中返回信息。我有它的工作,但后来收到了额外的要求,现在我无法弄清楚如何得到我想要的东西。
我有一个表格,其中包含可能包含在报告中的程序信息(基于进一步的要求)......此文件称为里程碑。 我有另一个表,其中包含与程序相关的项目 - 如果ID匹配 我有一个新表,有一个手动输入的覆盖结束日期 - 这是新的要求。里程碑表中有一个系统结束日期,但如果输入此覆盖日期,则它优先于系统结束日期。如果已输入覆盖日期,则异常文件将具有相同的程序ID和两个与里程碑表中的日期匹配的日期。
日期是yyyy-mm-dd格式化
Example data:
Milestones:
prgId | startDate | endDate
------------------------------
123 | 2014-03-09 | 2014-11-10
123 | 2014-07-10 | 2014-11-10
324 | 2014-05-09 | 2014-11-12
exceptions:
prgId | startDate | overEnd
-------------------------------
123 | 2014-03-09 | 2014-05-31
projects:
prgId | cust
-------------
123 | 12121
123 | 4323
我目前要归还的是:
prgId prjCnt startDate endDate overEnd
123 2 2014-03-09 2014-11-10 2014-05-31
123 2 2014-07-10 2014-11-10
324 0 2014-05-09 2014-11-12
我确实意识到,现在程序123的两个项目将显示两个行 - 我们将寻找一种方法将它们与正确的那些相关联,但还没有。
我们添加了覆盖日期要求,以便当前程序的报告不会同时显示“123”行,而只会显示当前程序(第二行)。
我当前的SELECT就像这样(对不起,我不能让它更容易显示它真的很长):
SELECT milestones.*, newtbl.prjcnt, exceptions.overEnd
FROM milestones
LEFT JOIN ((
SELECT prgGuid, count( prgGuid ) AS prjcnt
FROM projects
GROUP BY prgGuid
) AS newtbl )
ON milestones.prgId = newtbl.prgId
LEFT JOIN exceptions
ON (milestones.prgId = exceptions.prgId
AND milestones.startDate = exceptions.startDate)
WHERE <(milestones.startDate > '2013-00-00')
AND (milestones.startDate <= CURDATE() AND milestones.endDate >= CURDATE())
ORDER BY milestones.endDate, milestones.startDate DESC
现在我想要的是将此更改为仅抓取程序,项目计数,开始和结束日期以及开始日期为2013年至当前日期且尚未结束的程序的覆盖结束日期。现在....如果一个程序有一个覆盖结束日期并且该结束日期是当前的(&gt; =当前日期),那么它应该被包含但是如果覆盖日期是NULL或者&lt; =当前日期,我不想要包括它。
我想要归还的是:
prgId prjCnt startDate endDate overEnd
123 2 2014-07-10 2014-11-10
324 0 2014-05-09 2014-11-12
之前的第一行已过期,所以不应该显示。
我尝试了一些事情,但我最终没有结果,或者我得到了我目前得到的所有东西。
有人可以帮我弄清楚SELECT应该是什么吗?
答案 0 :(得分:1)
因此,如果我关注您,您的DDL可能如下所示:
CREATE TABLE MILESTONES
(`prgId` int, `startDate` varchar(10), `endDate` varchar(10))
;
INSERT INTO MILESTONES
(`prgId`, `startDate`, `endDate`)
VALUES
(123, '2014-03-09', '2014-11-10'),
(123, '2014-07-10', '2014-11-10'),
(324, '2014-05-09', '2014-11-12')
;
CREATE TABLE EXCEPTIONS
(`prgId` int, `startDate` varchar(10), `overEnd` varchar(10))
;
INSERT INTO EXCEPTIONS
(`prgId`, `startDate`, `overEnd`)
VALUES
(123, '2014-03-09', '2014-05-31')
;
CREATE TABLE PROJECTS
(`prgId` int, `cust` int)
;
INSERT INTO PROJECTS
(`prgId`, `cust`)
VALUES
(123, 12121),
(123, 4323)
;
您当前的查询不起作用(请注意我已根据您的问题更正了我认为是您的查询中的错别字):
SELECT milestones.*, newtbl.prjcnt, exceptions.overEnd
FROM milestones
LEFT JOIN ((
SELECT prgId, count( prgId ) AS prjcnt
FROM projects
GROUP BY prgId
) AS newtbl )
ON milestones.prgId = newtbl.prgId
LEFT JOIN exceptions
ON (milestones.prgId = exceptions.prgId
AND milestones.startDate = exceptions.startDate)
WHERE (milestones.startDate > '2013-00-00')
AND (milestones.startDate <= CURDATE() AND milestones.endDate >= CURDATE())
ORDER BY milestones.endDate, milestones.startDate DESC
工作解决方案如下所示:
SELECT DISTINCT
M.prgId as PRGID
, ( SELECT COUNT(X.prgID)
FROM PROJECTS X
WHERE X.prgID = M.prgID ) as PRJCNT
, M.startDate as STARTDATE
, M.endDate as ENDDATE
, COALESCE(E.overEnd,'') as OVEREND
FROM MILESTONES M
LEFT OUTER JOIN PROJECTS P
ON M.prgId = P.prgId
LEFT JOIN EXCEPTIONS E
ON M.prgId = E.prgId
AND M.startDate = E.startDate
WHERE M.startDate > '2013-01-01'
AND M.startDate <= CURDATE()
AND M.endDate >= CURDATE()
AND ( E.overEnd IS NULL
OR E.overEnd > CURDATE() )
您可以在此处看到它:SQLFiddle。
请注意,该解决方案依赖于COALESCE函数来实现干净输出,并且在WHERE子句中放置了更多业务规则。