SQL-具有COUNT()不能按预期工作

时间:2019-05-18 15:33:29

标签: mysql sql

我加入了几张桌子,并使用以下代码过滤了结果。

SELECT jmeno, prijmeni, adresa, vozidlo.spz, snimek.timestamp
FROM majitel
INNER JOIN vozidlo ON majitel.id_majitel = vozidlo.id_majitel
INNER JOIN kat_kamera ON kat_kamera.id_kategorie = vozidlo.id_kategorie
INNER JOIN snimek ON kat_kamera.id_kamera = snimek.id_kamera
WHERE TIMESTAMP >= TIMESTAMP(NOW() - INTERVAL 2 DAY)

这是结果。

jmeno   prijmeni    adresa  spz         timestamp
John    Doe         Prague  7A2 5109    17/05/2019 08:21
John    Doe         Prague  7A2 5109    17/05/2019 20:50
Vanessa Green       Pilsen  4P8 9370    17/05/2019 06:14
John    Doe         Prague  7A2 5109    17/05/2019 20:50
Vanessa Green       Pilsen  4P8 9370    17/05/2019 12:27
Vanessa Green       Pilsen  4P8 9370    17/05/2019 14:31
John    Doe         Prague  7A2 5109    18/05/2019 15:35

到目前为止,效果很好。问题是,我只想将结果限制为出现3次以上的结果。

所以我这样修改了查询。

SELECT jmeno, prijmeni, adresa, vozidlo.spz, snimek.timestamp
FROM majitel
INNER JOIN vozidlo ON majitel.id_majitel = vozidlo.id_majitel
INNER JOIN kat_kamera ON kat_kamera.id_kategorie = vozidlo.id_kategorie
INNER JOIN snimek ON kat_kamera.id_kamera = snimek.id_kamera
WHERE TIMESTAMP >= TIMESTAMP(NOW() - INTERVAL 2 DAY)
HAVING COUNT(jmeno) >= 3

但是不幸的是,这不起作用。因为它只返回这个。

jmeno   prijmeni    adresa  spz         timestamp
John    Doe         Prague  7A2 5109    17/05/2019 08:21

但最终结果中应同时包含 John Doe Vanessa Green

您能帮我得到想要的结果吗?

3 个答案:

答案 0 :(得分:1)

您需要一个GROUP BY。 MySQL允许HAVING子句不带有GROUP BY。整个查询被视为聚合查询,并且仅返回一行。

如果只需要重复的部分:

SELECT jmeno, prijmeni, adresa, v.spz
FROM majitel m INNER JOIN
     vozidlo v
     ON m.id_majitel = v.id_majitel INNER JOIN
     kat_kamera kk
     ON kk.id_kategorie = v.id_kategorie INNER JOIN
     snimek s
     ON kk.id_kamera = s.id_kamera
WHERE TIMESTAMP >= TIMESTAMP(NOW() - INTERVAL 2 DAY)
GROUP BY jmeno, prijmeni, adresa, v.spz
HAVING COUNT(*) >= 3;

(我建议您限定所有所有列名,以便清楚了解它们来自何表。)

要添加timestamp会比较棘手。也许在同一行中将它们串联在一起就足够了:

SELECT jmeno, prijmeni, adresa, v.spz,
       GROUP_CONCAT(timestamp) as timestamps
FROM majitel m INNER JOIN
     vozidlo v
     ON m.id_majitel = v.id_majitel INNER JOIN
     kat_kamera kk
     ON kk.id_kategorie = v.id_kategorie INNER JOIN
     snimek s
     ON kk.id_kamera = s.id_kamera
WHERE TIMESTAMP >= TIMESTAMP(NOW() - INTERVAL 2 DAY)
GROUP BY jmeno, prijmeni, adresa, v.spz
HAVING COUNT(*) >= 3;

如果需要单独的行,则在MySQL 8+中,可以使用窗口函数:

SELECT x.*
FROM (SELECT jmeno, prijmeni, adresa, v.spz, timestamp,
             COUNT(*) OVER (jmeno, prijmeni, adresa, v.spz) as cnt
      FROM majitel m INNER JOIN
           vozidlo v
           ON m.id_majitel = v.id_majitel INNER JOIN
           kat_kamera kk
           ON kk.id_kategorie = v.id_kategorie INNER JOIN
           snimek s
           ON kk.id_kamera = s.id_kamera
      WHERE TIMESTAMP >= TIMESTAMP(NOW() - INTERVAL 2 DAY)
      GROUP BY jmeno, prijmeni, adresa, v.spz
     ) x
WHERE cnt >= 3;

答案 1 :(得分:0)

您应该使用group by和count(*)

{{1}}

,并使用聚合函数来减少时间戳记值(例如:min())

答案 2 :(得分:0)

如果不想丢失有关每个时间戳的信息,可以通过使用ROW_NUMBEREXISTS来完成。试试这个:

WITH CTE AS
(
    SELECT 
         jmeno
        ,prijmeni
        ,adresa
        ,vozidlo.spz
        ,snimek.timestamp
        ,ROW_NUMBER() OVER (PARTITION BY jmeno ORDER BY jmeno) as number
    FROM majitel
    INNER JOIN vozidlo ON majitel.id_majitel = vozidlo.id_majitel
    INNER JOIN kat_kamera ON kat_kamera.id_kategorie = vozidlo.id_kategorie
    INNER JOIN snimek ON kat_kamera.id_kamera = snimek.id_kamera
    WHERE TIMESTAMP >= TIMESTAMP(NOW() - INTERVAL 2 DAY)
)
SELECT
    *
FROM CTE
WHERE exists (
                SELECT 1
                FROM CTE
                where CTE.jmeno = jmeno
                and CTE.number >= 3
              )