sql - 如何根据返回的记录数选择列?
问题描述
这是我的桌子
| prdntVrsnNum | matlNum | wrkCtrCd | ritmValFromDt | versnValFromDt | parmVldFromDt | rtgTypeCd | rtgGrpCd | rtgNodeNum | charVal |
| ------------ | ------- | -------- | ------------- | -------------- | ------------- | --------- | -------- | ---------- | ------- |
| V001 | 96228 | TO-HCH2 | 20170407 | 20170407 | 20170407 | N | 50020937 | 1 | 7 |
| V001 | 96228 | TO-HCH2 | 20170407 | 20170407 | 20170407 | N | 50020937 | 1 | 7 |
| V001 | 96228 | TO-HCH2 | 20170407 | 20170407 | 20180101 | N | 50020937 | 1 | 7 |
| V001 | 96228 | TO-HCH2 | 20170407 | 20170407 | 20180101 | N | 50020937 | 1 | 7 |
| V003 | 197774 | TOU-A16 | 20181210 | 20181207 | 20190107 | N | 50018492 | 6 | 1 |
| V003 | 197774 | TOU-A16 | 20181210 | 20181207 | 20190107 | N | 50018492 | 6 | 1 |
| V001 | 66850 | LI-LIN2 | 20180101 | 20141211 | 20141211 | N | 50018966 | 1 | 5 |
| V001 | 66850 | LI-LIN2 | 20180101 | 20141211 | 20151227 | N | 50018966 | 1 | 4.5 |
| V001 | 66850 | LI-LIN2 | 20180101 | 20141211 | 20141211 | N | 50018966 | 1 | 5 |
| V001 | 66850 | LI-LIN2 | 20180101 | 20141211 | 20151227 | N | 50018966 | 1 | 4.5 |
期望的结果:
TOU-A16/V003/197774/20181210
TO-HCH2/V001/96228/20180101
LI-LIN2/V001/66850/20180101
要求/条件:
prdntVrsnNum
, matlNum
,wrkCtrCd
作为关键列,
根据
rtgTypeCd
,rtgGrpCd
,rtgNodeNum
,parmVldFromDt
,删除重复项charVal
如果没有找到记录,什么也不做。
如果找到一条记录,则
ritmValFromDt
进行连接如果找到多条记录,查看有多少条记录
parmVldFromDt
>=ritmValFromDt
4.1。如果找到一条记录,则
ritmValFromDt
用于连接。4.2. 如果找到多条记录,则
parmVldFromDt
用于连接。
我用来解释的中间结果:
SELECT distinct * from mytable;
| prdntVrsnNum | matlNum | wrkCtrCd | ritmValFromDt | versnValFromDt | parmVldFromDt | rtgTypeCd | rtgGrpCd | rtgNodeNum | charVal |
| ------------ | ------- | -------- | ------------- | -------------- | ------------- | --------- | -------- | ---------- | ------- |
| V001 | 96228 | TO-HCH2 | 20170407 | 20170407 | 20170407 | N | 50020937 | 1 | 7 |
| V001 | 96228 | TO-HCH2 | 20170407 | 20170407 | 20180101 | N | 50020937 | 1 | 7 |
| V003 | 197774 | TOU-A16 | 20181210 | 20181207 | 20190107 | N | 50018492 | 6 | 1 |
| V001 | 66850 | LI-LIN2 | 20180101 | 20141211 | 20141211 | N | 50018966 | 1 | 5 |
| V001 | 66850 | LI-LIN2 | 20180101 | 20141211 | 20151227 | N | 50018966 | 1 | 4.5 |
从上表中,现在我应该将其简化为以下最终表,我将使用该表进行连接。
| prdntVrsnNum | matlNum | wrkCtrCd | ritmValFromDt | versnValFromDt | parmVldFromDt | rtgTypeCd | rtgGrpCd | rtgNodeNum | charVal |
| ------------ | ------- | -------- | ------------- | -------------- | ------------- | --------- | -------- | ---------- | ------- |
| V001 | 96228 | TO-HCH2 | 20170407 | 20170407 | 20180101 | N | 50020937 | 1 | 7 |
| V003 | 197774 | TOU-A16 | 20181210 | 20181207 | 20190107 | N | 50018492 | 6 | 1 |
| V001 | 66850 | LI-LIN2 | 20180101 | 20141211 | 20141211 | N | 50018966 | 1 | 5 |
| V001 | 66850 | LI-LIN2 | 20180101 | 20141211 | 20151227 | N | 50018966 | 1 | 4.5 |
编辑:进一步解释:
V001|96228|TO-HCH2
在条件下4.2
。V003|197774|TOU-A16
在条件下4.1
。V001|66850|LI-LIN2
我认为这种情况是通过选择来实现的,ritmValFromDt
因为这是更大的情况,而且我们没有任何关于这种组合的记录,parmVldFromDt >= ritmValFromDt
但我对此并不确定.. :(
DB-小提琴:https ://www.db-fiddle.com/f/qZLyGdyv2spYe3ZokZhYAP/1
到目前为止我已经尝试过:
SELECT
DISTINCT
CONCAT(wrkCtrCd, '/', prdntVrsnNum , '/', matlNum , '/', ritmValFromDt)
AS outputCol
FROM mytable;
| outputCol |
| ---------------------------- |
| TO-HCH2/V001/96228/20170407 |
| TOU-A16/V003/197774/20181210 |
SELECT
DISTINCT
CONCAT(wrkCtrCd, '/', prdntVrsnNum , '/', matlNum , '/',
CASE
WHEN parmVldFromDt >= ritmValFromDt THEN parmVldFromDt
ELSE ritmValFromDt
END)
AS outputCol
FROM mytable;
| outputCol |
| ---------------------------- |
| TO-HCH2/V001/96228/20170407 |
| TO-HCH2/V001/96228/20180101 |
| TOU-A16/V003/197774/20190107 |
笔记
使用 SQL 时,请尽可能保持供应商中立。这不在我的手中。我不是从源头查询,所以我的双手被束缚了。某些供应商特定的功能可能可用,但这不是保证。
在 db-fiddle 中,MySQL(和使用的版本)仅用于说明目的。如前所述,我不是从 RDBMS 查询,而是从网格查询,所以我必须根据可用的内容以及网格中可用的方式进行调整。
解决方案
我认为您没有正确定义您的条件。特别是,你对于最后一个条件,你似乎想要最晚的日期。
我会为此使用窗口功能。我认为逻辑是:
SELECT CONCAT(wrkCtrCd, '/', prdntVrsnNum , '/', matlNum , '/',
(CASE WHEN cnt = 1 OR cnt_gt = 1
THEN ritmValFromDt
ELSE parmVldFromDt
END)
) AS outputCol,
ritmValFromDt,parmVldFromDt
FROM (SELECT t.*,
COUNT(*) OVER (PARTITION BY prdntVrsnNum, matlNum, wrkCtrCd) as cnt,
SUM(gt_flag) OVER (PARTITION BY prdntVrsnNum, matlNum, wrkCtrCd) as cnt_gt,
ROW_NUMBER() OVER (PARTITION BY prdntVrsnNum, matlNum, wrkCtrCd, gt_flag ORDER BY parmVldFromDt DESC) as seqnum
FROM (SELECT DISTINCT prdntVrsnNum, matlNum, wrkCtrCd, ritmValFromDt, versnValFromDt, parmVldFromDt,
(CASE WHEN parmVldFromDt >= ritmValFromDt THEN 1 ELSE 0 END) as gt_flag
FROM mytable
) t
) t
WHERE (cnt_gt > 0 AND parmVldFromDt >= ritmValFromDt AND seqnum = 1) OR
(cnt_gt = 0);
这是一个 db<>fiddle。
推荐阅读
- angular - 素数树表选择未按预期工作
- java - JavaFX 折线图点操作
- python - ELMo 嵌入层与 Keras
- angular - 有没有办法使用 Angular 2 在一个 HTTP 请求中发送多个标头?
- javascript - window.location 然后 window.alert (立即关闭)(以避免在白屏时发出警报)
- php - SOAP 请求错误:SOAP 错误:服务器无法处理请求。---> MaskRequestInfo args(0) 不是字符串类型
- google-apps-script - 我的域中 Z 列中的用户时间戳
- entity-framework - 为什么当我尝试获取实体的属性时会得到一个 sql 查询?
- java - 无法使用 Jersey Maven 休息服务发送 Json 响应
- c++ - 由于 SDL_main 宏,Visual Studio 2017 无法使用 main 作为入口点