【问题标题】:SQL select max date that is smaller than specific dateSQL选择小于特定日期的最大日期
【发布时间】:2019-02-09 20:24:32
【问题描述】:

我试图在 Access 中进行查询,从表中选择 MAX 日期,该日期小于表中特定其他记录的日期,我必须检查该记录是否存在。

我知道描述有点混乱,所以我会尝试用伪代码解释它:

If(Record exists where editing_type = "Notranja kontrola")
   SELECT MAX(created_at) that is smaller than ( MIN(created_at) Where 
   editing_type = "Notranja kontrola") 
   WHERE editing_type = "Zajem"

如果editing_type = "Notranja kontrola" 的记录不存在,我不想选择日期。我想返回NULL。 如果是这样,我想选择最大日期 where editing_type = "Zajem",小于 MIN(date) WHERE editing_type = "Notranja kontrola")

我想出的查询:

SELECT 
spr.ob_id AS Obcina, 
spr.ko, 
'DA' AS Dodeljeno,
(   
SELECT MAX(created_at)
FROM ( 
    SELECT created_at
    FROM spremljanje_uporabnik_zajem
    WHERE created_at < (
        SELECT MIN(created_at)
        FROM spremljanje_uporabnik_zajem
        WHERE editing_type = "Notranja kontrola" AND ko = spr.ko AND VAL(ko) BETWEEN  0 AND 9999
        )
    )   
WHERE editing_type = "zajem" AND ko = spr.ko AND VAL(ko) BETWEEN  0 AND 9999
    AND EXISTS (
        SELECT 1
        FROM spremljanje_uporabnik_zajem
        WHERE editing_type = "Notranja kontrola" AND ko = spr.ko AND VAL(ko) BETWEEN  0 AND 9999
    )
) AS [krneki],

(SELECT
.....


)

FROM spremljanje_uporabnik_zajem AS spr

WHERE VAL(ko) BETWEEN  0 AND 9999

GROUP BY spr.ob_id, spr.ko

ORDER BY Val(spr.ko);

WHERE VAL(ko) BETWEEN 0 AND 9999 部分仅用于检查条目是否有效。

当我尝试运行查询时,我收到一个提示,要求我输入 spr.ko,而不是将其作为外部查询的值。 我该如何解决这个问题?

外部查询在那里,因为我还需要选择一些其他的东西。

编辑 + EDIT2: 我只从表“spremlanje_uporabniki_zajem”中选择

样本数据(spremlanje_uporabniki_zajem):

    ob_id   ko     editing_type        created_at
    40      100       zajem             1.01.2018
    40      100       zajem             2.01.2018
    40      100  notranja kontrola      3.01.2018
    40      100       zajem             4.01.2018
    90      550       zajem             2.01.2018
    40      100       zajem             6.01.2018
    40      20        zajem             7.01.2018
    40      20        zajem             8.01.2018
    40      20   notranja kontrola      9.01.2018
    40      20        zajem            10.01.2018
    40      100       zajem            11.01.2018
    40      20        zajem            12.01.2018
    40      20  notranja kontrola      13.01.2018
    40     100  notranja kontrola      13.01.2018


Expected REXPECTED RESULT:      


    ob_id    ko   Dodeljeno     krneki
      40    100      DA       2.01.2018
      90    550      DA          NULL
      40    20       DA       8.01.2018

谢谢

【问题讨论】:

  • 向我们展示数据库架构、示例数据、当前和预期输出。请阅读How-to-Ask 这里是START 了解如何提高问题质量并获得更好答案的好地方。 How to create a Minimal, Complete, and Verifiable example
  • 以文本形式发布表格和数据READ THIS
  • 抱歉,我知道我的问题令人困惑,但我不知道如何更好地解释它,英语不是我的主要语言。我将 datat 添加为文本。
  • 更多数据示例也有助于理解问题。并使用您的示例数据解释逻辑。包括多个 kontrola 行,以便我们可以看到 MIN、MAX 限制
  • 要格式化为code,选择文本并按ctrl-k或在每行前添加4个空格

标签: sql date ms-access max


【解决方案1】:
  • 首先您需要计算每个组的MIN(date)
  • 然后您执行 LEFT JOIN 以获取日期早于找到 MIN(date) 的行
  • 现在您将所有这些行组合在一起
  • 使用条件MAX(CASE) 可以删除具有空值的日期。

SQL DEMO

WITH cte as (
      SELECT  "ob_id", "ko", MIN("created_at") min_kontrola
      FROM Table1 
      WHERE "editing_type" = 'notranja kontrola'
      GROUP BY "ob_id", "ko"
)  
SELECT t."ob_id", 
       t."ko", 
       MAX(CASE WHEN c.min_kontrola IS NOT NULL 
                THEN t."created_at"
           END) as krneki
FROM Table1 t 
LEFT JOIN cte c
  ON t."ob_id" = c."ob_id"
 AND t."ko" = c."ko"
 AND t."created_at" < c.min_kontrola
GROUP BY t."ob_id", t."ko" 
ORDER BY  t."ob_id", t."ko";

输出

| ob_id |  ko |        max |
|-------|-----|------------|
|    40 |  20 | 2018-01-08 |
|    40 | 100 | 2018-01-02 |
|    90 | 550 |     (null) |

在 SQL DEMO 中有两个查询。第二个我删除了GROUP BY,这样你就可以在最后一步之前看到结果。

【讨论】:

  • MS Access 似乎不支持 CTE 的
  • 对不起,我错过了访问标签。但这并不意味着您不能将其重写为子查询,可以吗?
  • 谢谢,在弄清楚 CTE 的工作方式和修改查询以在访问中工作后,它按预期工作。
【解决方案2】:

也许您可以接受此查询并自己完成其余的工作。

select
  t3.ob_id,
  t3.ko,
  t4.max_created_at
from(
select distinct
  ob_id,
  ko
from dummyTable
) t3
left join (
SELECT
  t1.ob_id,
  t1.ko,
  max(t1.created_at) max_created_at
from dummyTable t1
where exists (
  select
    1
  from dummyTable t2
  where t2.ob_id = t1.ob_id and
  t2.ko = t1.ko and
  t2.editing_type = 'nontranja kontrola' and
  t1.created_at < t2.created_at
)) t4
on t4.ob_id = t3.ob_id and
t4.ko = t3.ko

你可以试试here

【讨论】:

【解决方案3】:

解决方案,以防万一有人感兴趣(修改自 @Juan Carlos Oropeza 帖子 - 用子查询替换 CTE 并使用 MS Access 语法)

SELECT 
    t.ob_id, 
    t.ko, 
    MAX(iif(c.min_kontrola IS NOT NULL,t.created_at)) as krneki,

FROM spremljanje_uporabnik_zajem t

LEFT JOIN 
    (
    SELECT  ob_id, ko, MIN(created_at) AS min_kontrola
    FROM spremljanje_uporabnik_zajem 
    WHERE editing_type = 'notranja kontrola'
    GROUP BY ob_id, ko
    )AS c

ON (t.ob_id = c.ob_id
AND t.ko = c.ko
AND (t.created_at < c.min_kontrola)
AND VAL(t.ko) BETWEEN 0 AND 9999
AND t.editing_type = "zajem"
)
GROUP BY t.ob_id, t.ko 
ORDER BY  t.ob_id, t.ko;

【讨论】:

    【解决方案4】:

    在理解了“NULL 要求”之后,我不得不修改我的答案。您的查询还不错,但我发现了一些需要改进/纠正的地方:

    • “zajem WHERE 子句”不能是 WHERE 子句,而是下一层 WHERE 子句的附加条件。
    • “EXISTS 标准”可以去掉,因为当不存在记录时,MIN 也不存在,因此与任何“zajem 记录”的比较都会失败,这将导致“没有最大值”( NULL) 根据需要。
    • 不需要“zajem 子查询”,可以直接在“MAX 查询”中应用条件。

    结果如下:

    SELECT 
        spr.ob_id AS Obcina
      , spr.ko
      , 'DA' AS Dodeljeno
      , (   
            SELECT MAX(created_at)
            FROM spremljanje_uporabnik_zajem
            WHERE editing_type = "zajem" AND ko = spr.ko AND VAL(ko) BETWEEN  0 AND 9999
              AND created_at < (
                SELECT MIN(created_at)
                FROM spremljanje_uporabnik_zajem
                WHERE editing_type = "Notranja kontrola" AND ko = spr.ko AND VAL(ko) BETWEEN  0 AND 9999
                )
        ) AS [krneki]
    FROM spremljanje_uporabnik_zajem AS spr
    WHERE VAL(ko) BETWEEN  0 AND 9999
    GROUP BY spr.ob_id, spr.ko
    ORDER BY VAL(spr.ko);
    

    Access 可以在没有任何问题的情况下运行它:

    【讨论】:

    • 此查询不返回 NULL 行。
    • @KrEn 你说如果editing_type = "Notranja kontrola" 的记录不存在,我不想选择日期。这不是意味着什么都不会出现吗?
    • 我的错,在这种情况下,我想在“krneki”字段中返回 NULL,但仍然选择其他内容(参见预期结果表)
    • @KrEn 现在,我想我明白你的意思了,我修改了我的答案(完全)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多