我正在搜索最近和最近的一张桌子记录。我正在使用TABLE(A和B)的两个实例,由DATE区分,或者如果在同一个DATE存在多个条目,则由SEQUENCE区分。我在WHERE子句中使用CASE来区分两个事件:1。A和B有不同的日期,2。A和B具有相同的日期,但是SEQUENCE号不同。我的CASE条款中的某些内容无效。我非常感谢您提供的任何帮助:
SELECT * FROM TABLE A, TABLE B
WHERE A.PERSON_ID = B.PERSON_ID
AND A.DATE >= B.DATE
AND A.DATE = (SELECT MAX(A1.DATE) FROM TABLE A1
WHERE A.PERSON_ID = A1.PERSON_ID)
AND A.SEQUENCE = (SELECT MAX(A2.SEQUENCE) FROM TABLE A2
WHERE A.PERSON_ID = A2.PERSON_ID
AND A.DATE = A2.DATE)
CASE IF A.DATE > B.DATE
THEN (B.DATE = (SELECT MAX(B1.DATE) FROM TABLE B1
WHERE B.PERSON_ID = B1.PERSON_ID
AND B.SEQUENCE = (SELECT MAX(B2.SEQUENCE) FROM TABLE B2
WHERE B.PERSON_ID = B2.PERSON_ID
AND B.DATE = B2.DATE))
ELSE (B.SEQUENCE = (SELECT MAX(B2.SEQUENCE) FROM TABLE B2
WHERE B.PERSION_ID = B2.PERSON_ID
AND B.DATE = B2.DATE
AND B2.SEQUENCE < A.SEQUENCE))
END
这是错误:
执行S1000期间出错(933)[Oracle] [ODBC] [Ora] ORA-00933:SQL命令未正确结束(0.09秒)
答案 0 :(得分:1)
在CASE
子句中使用WHERE
几乎总是一个错误。 SQL中存在CASE
主要是为了允许布尔逻辑,否则不允许这样做(例如在列列表中)。由于WHERE
子句的整个目的是表达布尔逻辑,CASE
只会混淆事物。
目前尚不清楚你想要完成什么。我最好的猜测是以下查询符合您的需求:
SELECT *
FROM table_a a JOIN table_b b ON a.person_id = b.person_id
WHERE a.date = (SELECT MAX (a1.date)
FROM table_a a1
WHERE a.person_id = a1.person_id)
AND a.sequence =
(SELECT MAX (a2.sequence)
FROM table_a a2
WHERE a.person_id = a2.person_id AND a.date = a2.date)
AND ( ( a.date > b.date
AND b.date =
(SELECT MAX (b1.date)
FROM table_b b1
WHERE b.person_id = b1.person_id
AND b.sequence =
(SELECT MAX (b2.sequence)
FROM table_b b2
WHERE b.person_id = b2.person_id
AND b.date = b2.date)))
OR (b.sequence =
(SELECT MAX (b2.sequence)
FROM table_b b2
WHERE b.persion_id = b2.person_id
AND b.date = b2.date
AND b2.sequence < a.sequence)))
答案 1 :(得分:0)
在case语句
中稍微语法更改后,查询错误已得到纠正SELECT * FROM TABLE A, TABLE B
WHERE A.PERSON_ID = B.PERSON_ID
AND A.DATE >= B.DATE
AND A.DATE = (SELECT MAX(A1.DATE) FROM TABLE A1
WHERE A.PERSON_ID = A1.PERSON_ID)
AND A.SEQUENCE = (SELECT MAX(A2.SEQUENCE) FROM TABLE A2
WHERE A.PERSON_ID = A2.PERSON_ID
AND A.DATE = A2.DATE)
AND 1 = (CASE WHEN A.DATE > B.DATE
THEN (CASE WHEN (B.DATE = (SELECT MAX(B1.DATE) FROM TABLE B1
WHERE B.PERSON_ID = B1.PERSON_ID
AND B.SEQUENCE = (SELECT MAX(B2.SEQUENCE) FROM TABLE B2
WHERE B.PERSON_ID = B2.PERSON_ID
AND B.DATE = B2.DATE))) THEN 1 ELSE 0 END)
ELSE (CASE WHEN (B.SEQUENCE = (SELECT MAX(B2.SEQUENCE) FROM TABLE B2
WHERE B.PERSON_ID = B2.PERSON_ID
AND B.DATE = B2.DATE
AND B2.SEQUENCE < A.SEQUENCE)) THEN 1 ELSE 0 END)
END)
最后一行
"WHERE B.PERSION_ID = B2.PERSON_ID"
更改为
"WHERE B.PERSON_ID = B2.PERSON_ID"
答案 2 :(得分:0)
我正在搜索最近和最近的一张桌子记录。
使用ROW_NUMBER() OVER (...)
更简单:
Oracle 11g R2架构设置 - 测试数据:
CREATE TABLE TABLE_NAME ( PERSON_ID, "DATE", "SEQUENCE" ) AS
SELECT 1, DATE '2015-06-26', 1 FROM DUAL
UNION ALL SELECT 1, DATE '2015-06-26', 2 FROM DUAL
UNION ALL SELECT 1, DATE '2015-06-27', 1 FROM DUAL
UNION ALL SELECT 2, DATE '2015-06-26', 1 FROM DUAL
UNION ALL SELECT 3, DATE '2015-06-26', 1 FROM DUAL
UNION ALL SELECT 3, DATE '2015-06-26', 4 FROM DUAL
UNION ALL SELECT 3, DATE '2015-06-27', 3 FROM DUAL
UNION ALL SELECT 3, DATE '2015-06-27', 2 FROM DUAL
UNION ALL SELECT 3, DATE '2015-06-27', 1 FROM DUAL
UNION ALL SELECT 4, DATE '2015-06-26', 1 FROM DUAL
UNION ALL SELECT 4, DATE '2015-06-26', 2 FROM DUAL
UNION ALL SELECT 4, DATE '2015-06-27', 3 FROM DUAL;
查询1 - 不同行上的第一个和第二个条目:
SELECT *
FROM (
SELECT t.*,
ROW_NUMBER() OVER ( PARTITION BY PERSON_ID ORDER BY "DATE" DESC, "SEQUENCE" DESC ) AS RN
FROM TABLE_NAME t
)
WHERE RN <= 2
<强> Results 强>:
| PERSON_ID | DATE | SEQUENCE | RN |
|-----------|------------------------|----------|----|
| 1 | June, 27 2015 00:00:00 | 1 | 1 |
| 1 | June, 26 2015 00:00:00 | 2 | 2 |
| 2 | June, 26 2015 00:00:00 | 1 | 1 |
| 3 | June, 27 2015 00:00:00 | 3 | 1 |
| 3 | June, 27 2015 00:00:00 | 2 | 2 |
| 4 | June, 27 2015 00:00:00 | 3 | 1 |
| 4 | June, 26 2015 00:00:00 | 2 | 2 |
查询2 - 同一行的第一个和第二个条目:
SELECT PERSON_ID,
FIRST_DATE,
FIRST_SEQUENCE,
SECOND_DATE,
SECOND_SEQUENCE
FROM (
SELECT PERSON_ID,
"DATE" AS FIRST_DATE,
"SEQUENCE" AS FIRST_SEQUENCE,
LEAD( "DATE" ) OVER ( PARTITION BY PERSON_ID ORDER BY "DATE" DESC, "SEQUENCE" DESC ) AS SECOND_DATE,
LEAD( "SEQUENCE" ) OVER ( PARTITION BY PERSON_ID ORDER BY "DATE" DESC, "SEQUENCE" DESC ) AS SECOND_SEQUENCE,
ROW_NUMBER() OVER ( PARTITION BY PERSON_ID ORDER BY "DATE" DESC, "SEQUENCE" DESC ) AS RN
FROM TABLE_NAME t
)
WHERE RN = 1
<强> Results 强>:
| PERSON_ID | FIRST_DATE | FIRST_SEQUENCE | SECOND_DATE | SECOND_SEQUENCE |
|-----------|------------------------|----------------|------------------------|-----------------|
| 1 | June, 27 2015 00:00:00 | 1 | June, 26 2015 00:00:00 | 2 |
| 2 | June, 26 2015 00:00:00 | 1 | (null) | (null) |
| 3 | June, 27 2015 00:00:00 | 3 | June, 27 2015 00:00:00 | 2 |
| 4 | June, 27 2015 00:00:00 | 3 | June, 26 2015 00:00:00 | 2 |
答案 3 :(得分:0)
感谢您的帮助。我不确定OVER和PARTITION BY会如何发挥作用。以下是我最终使用的内容:
SELECT *
FROM TABLE A, TABLE B
WHERE A.PERSON_ID = B.PERSON_ID
AND A.DATE >= B.DATE
AND A.DATE = (SELECT MAX(A1.DATE) FROM TABLE A1
WHERE A.PERSON_ID = A1.PERSON_ID)
AND A.SEQUENCE = (SELECT MAX(A2.SEQUENCE) FROM TABLE A2
WHERE A.PERSON_ID = A2.PERSON_ID
AND A.DATE = A2.DATE)
AND ((A.DATE = B.DATE
AND B.DATE = (SELECT MAX(B1.DATE) FROM TABLE B1
WHERE B.PERSON_ID = B1.PERSON_ID)
AND B.SEQUENCE = (SELECT MAX(B2.SEQUENCE) FROM TABLE B2
WHERE B.PERSON_ID = B2.PERSON_ID
AND B.DATE = B2.DATE
AND B.SEQUENCE < A.SEQUENCE))
OR (A.DATE > B.DATE
AND B.DATE = (SELECT MAX(B1.DATE) FROM TABLE B1
WHERE B.PERSON_ID = B1.PERSON_ID
AND B1.DATE < A.DATE)
AND B.SEQUENCE = (SELECT MAX(B2.SEQUENCE) FROM TABLE B2
WHERE B.PERSON_ID = B_ES.PERSON_ID
AND B.DATE = B2.DATE)))
ORDER BY A.PERSON_ID, B.SEQUENCE