SQL查找表

时间:2016-11-25 19:52:10

标签: mysql sql

美好的一天。

我似乎正在努力解决看似简单的问题。

我有一个表格,其值与有限数量的ID的日期(每月)相关

即。表1

ID | Date ---| Value 
01 | 2015-01 | val1
01 | 2015-02 | val2
02 | 2015-01 | val1
02 | 2015-03 | val2

因此ID:02没有2015-02日期的值。

我想返回没有值的所有ID和日期。 日期范围是:从表1中选择不同的日期

我似乎无法在选择和加入同一桌面之外思考。

我需要在我的选择中包含ID,我可以以某种方式选择该ID存在的ID和日期范围,并与整个日期范围进行比较,以获取不在“ID”中的每个ID的所有日期整个“日期范围。

请指教。 谢谢

4 个答案:

答案 0 :(得分:0)

你的最后两句话不太清楚。但是您可以使用不同的@max_days和@min_date来播放以下查询:

-- DROP TABLE table1;
CREATE TABLE table1(ID int not null, `date` date not null, value varchar(64) not null);
INSERT table1(ID,`date`,value)
VALUES (1,'2015-01-01','v1'),(1,'2015-01-02','v2'),(2,'2015-01-01','v1'),(2,'2015-01-03','v2'),(4,'2015-01-01','v1'),(4,'2015-01-04','v2');
SELECT * FROM table1;

SET @day=0;
SET @max_days=5;
SET @min_date='2015-01-01';

SELECT i.ID,d.`date`
FROM (SELECT DISTINCT ID FROM table1) i
CROSS JOIN (
  SELECT TIMESTAMPADD(DAY,@day,@min_date) AS `date`,@day:=@day+1 AS day_num
  FROM table1 WHERE @day<@max_days) d
LEFT JOIN table1 t
ON t.ID=i.ID
AND t.`date`=d.`date`
WHERE t.`date` IS NULL
ORDER BY i.ID,d.`date`;

答案 1 :(得分:0)

我现在明白你要求从表中提取日期;您想在每个ID 的日期范围中找到任何空白。

这可以满足您的需求,但可以改进。下面的说明,您可以查看working example

DROP TABLE IF EXISTS Table1;
DROP TABLE IF EXISTS Year_Month_Calendar;

CREATE TABLE Table1 (
    id INTEGER
    ,date CHAR(7)
    ,value CHAR(4)
);

INSERT INTO Table1
VALUES
     (1,'2015-01','val1')
    ,(1,'2015-02','val2')
    ,(2,'2015-01','val1')
    ,(2,'2015-03','val1');

CREATE TABLE Year_Month_Calendar (
    date CHAR(10)
);

INSERT INTO Year_Month_Calendar
VALUES
     ('2015-01')
    ,('2015-02')
    ,('2015-03');

SELECT ID_Year_Month.id, ID_Year_Month.date, Table1.id, Table1.date
FROM ( 
    SELECT Distinct_ID.id, Year_Month_Calendar.date
    FROM Year_Month_Calendar
    CROSS JOIN 
        ( SELECT DISTINCT id FROM Table1 ) AS Distinct_ID
    WHERE Year_Month_Calendar.date >= (SELECT MIN(date) FROM Table1 WHERE id=Distinct_ID.ID)
        AND Year_Month_Calendar.date <= (SELECT MAX(date) FROM Table1 WHERE id=Distinct_ID.ID)
) AS ID_Year_Month
LEFT JOIN Table1
    ON ID_Year_Month.id = Table1.id AND ID_Year_Month.date = Table1.date
-- WHERE Table1.id IS NULL
ORDER BY ID_Year_Month.id, ID_Year_Month.date

说明

您需要一个日历表,其中包含所有日期(年/月),以涵盖您要查询的数据。

CREATE TABLE Year_Month_Calendar (
    date CHAR(10)
);

INSERT INTO Year_Month_Calendar
VALUES
     ('2015-01')
    ,('2015-02')
    ,('2015-03');

内部选择会创建一个表格,其中包含每个id的最小和最大日期之间的所有日期。

SELECT Distinct_ID.id, Year_Month_Calendar.date
FROM Year_Month_Calendar
CROSS JOIN 
    ( SELECT DISTINCT id FROM Table1 ) AS Distinct_ID
WHERE Year_Month_Calendar.date >= (SELECT MIN(date) FROM Table1 WHERE id=Distinct_ID.ID)
    AND Year_Month_Calendar.date <= (SELECT MAX(date) FROM Table1 WHERE id=Distinct_ID.ID)

然后LEFT JOINED到原始表以查找缺失的行。

如果您只想返回缺失的行(我的查询显示整个表以显示它的工作原理),请添加WHERE子句以将输出限制为id和{表1中未返回{1}}

评论前的原始答案

您可以在没有计数表的情况下执行此操作,因为您说

  

日期范围是:从Table1中选择不同的日期

我稍微更改了字段名称以避免SQL中的保留字。

date

我没有过滤结果,以显示查询是如何工作的。要返回仅缺少日期的行,请将SELECT id_table.ID, date_table.`year_month`, table1.val FROM (SELECT DISTINCT ID FROM table1) AS id_table CROSS JOIN (SELECT DISTINCT `year_month` FROM table1) AS date_table LEFT JOIN table1 ON table1.ID=id_table.ID AND table1.`year_month` = date_table.`year_month` ORDER BY id_table.ID 添加到外部查询。

SQL Fiddle

答案 2 :(得分:-1)

您需要一个计数表或月/年表。因此,您可以生成要测试的所有潜在组合。至于如何使用它你的例子可以使用一些扩展,例如过去12个月,过去3个月等等。但这里有一个例子可以帮助你理解你在寻找:

http://rextester.com/ZDQS5259

CREATE TABLE IF NOT EXISTS Tbl (
    ID INTEGER
    ,Date VARCHAR(10)
    ,Value VARCHAR(10)
);

INSERT INTO Tbl VALUES
(1,'2015-01','val1')
,(1,'2015-02','val2')
,(2,'2015-01','val1')
,(2,'2015-03','val1');


SELECT yr.YearNumber, mn.MonthNumber, i.Id
FROM
    (
       SELECT 2016 as YearNumber
       UNION SELECT 2015
    ) yr
    CROSS JOIN (
       SELECT 1 MonthNumber
       UNION SELECT 2
       UNION SELECT 3
       UNION SELECT 4
       UNION SELECT 5
       UNION SELECT 6
       UNION SELECT 7
       UNION SELECT 8
       UNION SELECT 9
       UNION SELECT 10
       UNION SELECT 11
       UNION SELECT 12
    ) mn
    CROSS JOIN (
       SELECT DISTINCT ID
       FROM
          Tbl
    ) i
    LEFT JOIN Tbl t
    ON yr.YearNumber = CAST(LEFT(t.Date,4) as UNSIGNED)
    AND mn.MonthNumber = CAST(RIGHT(t.Date,2) AS UNSIGNED)
    AND i.ID = t.ID
WHERE
    t.ID IS NULL

确定你不知道的基本想法是生成所有可能的组合。例如。年X月X DISTINCT Id,然后再加入以找出遗漏的内容。

答案 3 :(得分:-1)

可能不是最漂亮的,但这应该有用。

select distinct c.ID, c.Date, d.Value
from (select a.ID, b.Date
from (select distinct ID from Table1) as a, (select distinct Date from Table1) as b) as c
left outer join Table1 d on (c.ID = d.ID and c.Date = d.Date)
where d.Value is NULL