没有WHERE语句的INT比较

时间:2014-01-23 14:39:45

标签: mysql sql select group-by pivot

我试着写一个MySQL语句,它会把这些结果带回来:

## Name | Day 0 | Day 1 | Day 2 | Day 3 | Day 4 | Day 5 |
##Jeff  |   0   |    3  |     1 |     2 |    1  |   1   |
##Larry |   1   |    1  |     4 |     4 |    1  |   0   |

根据每位员工每天执行的任务数量。

我的数据库表如下:

员工

id(INT),number(VARCHAR),name(VARCHAR),dateStarted(VARCHAR),

项目

id(INT),number(VARCHAR),dateEnded(DATETIME)

现在我正在使用这个声明:

SELECT 
a.name AS "Name",
count(abs(datediff(STR_TO_DATE(a.dateStarted, '%Y-%m-%d %H:%i:%s'), b.dateEnded))) AS "Day 0",
count(abs(datediff(STR_TO_DATE(a.dateStarted, '%Y-%m-%d %H:%i:%s'), b.dateEnded))) AS "Day 1",
count(abs(datediff(STR_TO_DATE(a.dateStarted, '%Y-%m-%d %H:%i:%s'), b.dateEnded))) AS "Day 2",
count(abs(datediff(STR_TO_DATE(a.dateStarted, '%Y-%m-%d %H:%i:%s'), b.dateEnded))) AS "Day 3",
count(abs(datediff(STR_TO_DATE(a.dateStarted, '%Y-%m-%d %H:%i:%s'), b.dateEnded))) AS "Day 4",
count(abs(datediff(STR_TO_DATE(a.dateStarted, '%Y-%m-%d %H:%i:%s'), b.dateEnded))) AS "Day 5"
FROM employee a, project b
WHERE b.number=a.number 
AND "Day 0" = 0
AND "Day 1" = 1
AND "Day 2" = 2
AND "Day 3" = 3
AND "Day 4" = 4
AND "Day 5" >= 5

当前输出

Current Undesired Output

以上陈述有效,但由于某种原因,它无法提供上述要求中提到的理想结果。关于如何修复/更改它的任何想法?

修改

如果我拿出来:

AND "Day 0" = 0
AND "Day 1" = 1
AND "Day 2" = 2
AND "Day 3" = 3
AND "Day 4" = 4
AND "Day 5" >= 5

然后打印出来:

## Name | Day 0 | Day 1 | Day 2 | Day 3 | Day 4 | Day 5 |
##Jeff  |   9   |    9  |     9 |     9 |    9  |   9   |

4 个答案:

答案 0 :(得分:1)

试试这个:

SELECT
  emp.name AS '## Name',
  (SELECT COUNT(*)     
   FROM project p JOIN employee e ON p.number = e.number
   WHERE e.name = emp.name 
     AND datediff(str_to_date(p.dateEnded, '%Y-%m-%d'), e.dateStarted) = 0
   ) AS 'Day 0'
  ,(SELECT COUNT(*)
    FROM project p JOIN employee e ON p.number = e.number
    WHERE e.name = emp.name 
      AND datediff(str_to_date(p.dateEnded, '%Y-%m-%d'), e.dateStarted) = 1
   ) AS 'Day 1'
  ,(SELECT COUNT(*)
    FROM project p JOIN employee e ON p.number = e.number
    WHERE e.name = emp.name 
      AND datediff(str_to_date(p.dateEnded, '%Y-%m-%d'), e.dateStarted) = 2
   ) AS 'Day 2'
  ,(SELECT COUNT(*)
    FROM project p JOIN employee e ON p.number = e.number
    WHERE e.name = emp.name 
      AND datediff(str_to_date(p.dateEnded, '%Y-%m-%d'), e.dateStarted) = 3
   ) AS 'Day 3'
  ,(SELECT COUNT(*)
    FROM project p JOIN employee e ON p.number = e.number
    WHERE e.name = emp.name 
      AND datediff(str_to_date(p.dateEnded, '%Y-%m-%d'), e.dateStarted) = 4
   ) AS 'Day 4'
  ,(SELECT COUNT(*)
    FROM project p JOIN employee e ON p.number = e.number
    WHERE e.name = emp.name 
      AND datediff(str_to_date(p.dateEnded, '%Y-%m-%d'), e.dateStarted) >= 5
   ) AS 'Day 5'
FROM employee emp
GROUP BY emp.name

请参阅SQL Fiddle Demo( - 已根据提供的信息对您的数据做出一些假设)。

答案 1 :(得分:1)

试试这个:

SELECT a.name AS "Name", 
       SUM(noOfDays = 0) AS "Day 0", SUM(noOfDays = 1) AS "Day 1", 
       SUM(noOfDays = 2) AS "Day 2", SUM(noOfDays = 3) AS "Day 3", 
       SUM(noOfDays = 4) AS "Day 4", SUM(noOfDays >= 5) AS "Day 5", 
       COUNT(1) AS "Total Days"
FROM (SELECT a.name, DATEDIFF(DATE(b.dateEnded), DATE(a.dateStarted)) noOfDays
      FROM employee a INNER JOIN project b ON b.number = a.number 
      WHERE b.dateEnded IS NOT NULL
    ) AS A
GROUP BY a.name;

检查SQL FIDDLE DEMO

|    NAME | DAY 0 | DAY 1 | DAY 2 | DAY 3 | DAY 4 | DAY 5 | TOTAL DAYS |
|---------|-------|-------|-------|-------|-------|-------|------------|
|  ##Jeff |     0 |     3 |     1 |     2 |     1 |     1 |          8 |
| ##Larry |     1 |     1 |     4 |     4 |     1 |     0 |         11 |

答案 2 :(得分:1)

通过执行以下连接语句或其中..

,可以改进以前的解决方案

确保在项目上有一个索引(唯一?)(number,dateEnded) 您还可以尝试在employee(number,dateStarted)上添加索引

NULL值通常不是任何索引的一部分(因为它们是null),您可以尝试将该字段的默认值更新为“0000-00-00”,这样它将被索引并可能增加速度。 / p>

试试这个:

SELECT a.name AS "Name", 
       SUM(noOfDays = 0) AS "Day 0", SUM(noOfDays = 1) AS "Day 1", 
       SUM(noOfDays = 2) AS "Day 2", SUM(noOfDays = 3) AS "Day 3", 
       SUM(noOfDays = 4) AS "Day 4", SUM(noOfDays >= 5) AS "Day 5" 
FROM (SELECT a.number, a.name, DATEDIFF(DATE(b.dateEnded), DATE(a.dateStarted)) noOfDays
      FROM employee a INNER JOIN project b ON (b.number = a.number and b.dateEnded>a.dateStarted)
    ) AS a
GROUP BY a.name

检查SQL FIDDLE DEMO

|    NAME | DAY 0 | DAY 1 | DAY 2 | DAY 3 | DAY 4 | DAY 5 |
|---------|-------|-------|-------|-------|-------|-------|
|  ##Jeff |     0 |     3 |     1 |     2 |     1 |     1 |
| ##Larry |     1 |     1 |     4 |     4 |     1 |     0 |

答案 3 :(得分:0)

使用之前答案之一的SQL小提琴数据,我试过这个: -

SELECT Sub0.name AS "Name", 
    SUM(IF(DayDesc = 0 AND DaysCount IS NOT NULL, 1, 0)) AS "Day 0",
    SUM(IF(DayDesc = 1 AND DaysCount IS NOT NULL, 1, 0)) AS "Day 1",
    SUM(IF(DayDesc = 2 AND DaysCount IS NOT NULL, 1, 0)) AS "Day 2",
    SUM(IF(DayDesc = 3 AND DaysCount IS NOT NULL, 1, 0)) AS "Day 3",
    SUM(IF(DayDesc = 4 AND DaysCount IS NOT NULL, 1, 0)) AS "Day 4",
    SUM(IF(DayDesc = 5 AND DaysCount IS NOT NULL, 1, 0)) AS "Day 5"
FROM
(
    SELECT DISTINCT name FROM employee
)Sub0
CROSS JOIN
(
    SELECT 0 AS DayMin, 0 AS DayMax, 0 AS DayDesc
    UNION
    SELECT 1 AS DayMin, 1 AS DayMax, 1 AS DayDesc
    UNION
    SELECT 2 AS DayMin, 2 AS DayMax, 2 AS DayDesc
    UNION
    SELECT 3 AS DayMin, 3 AS DayMax, 3 AS DayDesc
    UNION
    SELECT 4 AS DayMin, 4 AS DayMax, 4 AS DayDesc
    UNION
    SELECT 5 AS DayMin, 999999999 AS DayMax, 5 AS DayDesc
) Sub1
LEFT OUTER JOIN 
(
    SELECT a.name, ABS(DATEDIFF(STR_TO_DATE(a.dateStarted, '%Y-%m-%d %H:%i:%s'), b.dateEnded)) DaysCount
    FROM employee a
    INNER JOIN project b
    ON b.number = a.number 
) Sub2
ON Sub2.DaysCount BETWEEN Sub1.DayMin AND Sub1.DayMax
AND Sub2.name = Sub0.name
GROUP BY Sub0.name

似乎能给出正确的结果而且速度很快。

SQL小提琴: -

http://www.sqlfiddle.com/#!2/db498/84

效率更高(但不能应对没有项目的员工): -

SELECT Sub0.name AS "Name", 
    SUM(IF(DayDesc = 0, 1, 0)) AS "Day 0",
    SUM(IF(DayDesc = 1, 1, 0)) AS "Day 1",
    SUM(IF(DayDesc = 2, 1, 0)) AS "Day 2",
    SUM(IF(DayDesc = 3, 1, 0)) AS "Day 3",
    SUM(IF(DayDesc = 4, 1, 0)) AS "Day 4",
    SUM(IF(DayDesc = 5, 1, 0)) AS "Day 5"
FROM
(
    SELECT a.name, 
        CASE ABS(DATEDIFF(STR_TO_DATE(a.dateStarted, '%Y-%m-%d %H:%i:%s'), b.dateEnded))
            WHEN 0 THEN 0
            WHEN 1 THEN 1
            WHEN 2 THEN 2
            WHEN 3 THEN 3
            WHEN 4 THEN 4
            ELSE 5
        END AS DayDesc
    FROM employee a
    INNER JOIN project b
    ON b.number = a.number 
) Sub0
GROUP BY Sub0.name

SQL小提琴: -

http://www.sqlfiddle.com/#!2/db498/89