Mysql 复杂的SELECT语句包含多个未返回所需结果的联接

Mysql 复杂的SELECT语句包含多个未返回所需结果的联接,mysql,join,relational-database,Mysql,Join,Relational Database,我正在尝试创建一个SELECT来从几个表返回信息。我有它的工作,但后来收到了一个额外的要求,现在我有困难,找出如何得到我想要的 我有一个表格,其中包含了根据进一步要求可以包含在报告中的计划信息……该文件称为里程碑。 我有另一个表,其中包含与程序相关的项目-如果ID匹配 我有一个手动输入覆盖结束日期的新表-这是新的要求。里程碑表中有一个系统结束日期,但如果输入了此覆盖日期,则其优先于系统结束日期。如果输入了覆盖日期,异常文件将具有相同的程序ID和两个与里程碑表中的日期匹配的日期 日期采用YY-mm

我正在尝试创建一个SELECT来从几个表返回信息。我有它的工作,但后来收到了一个额外的要求,现在我有困难,找出如何得到我想要的

我有一个表格,其中包含了根据进一步要求可以包含在报告中的计划信息……该文件称为里程碑。 我有另一个表,其中包含与程序相关的项目-如果ID匹配 我有一个手动输入覆盖结束日期的新表-这是新的要求。里程碑表中有一个系统结束日期,但如果输入了此覆盖日期,则其优先于系统结束日期。如果输入了覆盖日期,异常文件将具有相同的程序ID和两个与里程碑表中的日期匹配的日期

日期采用YY-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 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 
之前的第一行已过期,因此不应显示

我尝试了一些方法,但我要么没有结果,要么得到了我目前得到的一切


有人能帮我弄清楚SELECT应该是什么吗?

所以如果我跟着你,你的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 
工作解决方案如下所示:

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)
;
您可以在此处看到它的作用:


请注意,该解决方案依赖于COALESCE函数以获得干净的输出,并在WHERE子句中放置更多的业务规则。

而不是尝试将所有结束日期覆盖条件放入联接中,只需在不带额外条件的情况下外部连接到异常表,并在SELECT子句中使用CASE语句将您想要的规则应用到output override date列。我从来没有这样做过。您是否碰巧有一个示例?仔细看一下,很明显,您实际上不需要在SELECT中使用CASE语句。这只是一个修正WHERE条款的问题。请看下面我的完整答案。非常感谢。我试试看。我看了这个案子,觉得也行不通。我以前没有用过COALESCE,所以我也会研究一下。谢谢!它工作得很好。我非常感谢你的帮助。
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() )