如何根据返回的记录数选择列?

时间:2019-03-26 09:01:17

标签: 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

要求/条件:

prdntVrsnNummatlNumwrkCtrCd作为键列,

  1. 根据rtgTypeCdrtgGrpCdrtgNodeNumparmVldFromDtcharVal

  2. 删除重复项
  3. 如果未找到任何记录,则不执行任何操作。

  4. 如果找到一条记录,请ritmValFromDt进行串联

  5. 如果找到多个记录,请查看有多少记录具有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 |

注意

  1. 使用SQL时,请尽可能与供应商无关。这不在我手中。我不是从来源查询,所以我的双手被绑住了。某些特定于供应商的功能可能可用,但这不是保证。

  2. 在db-fiddle中,MySQL(和使用的版本)仅用于说明目的。如前所述,我不是从RDBMS查询,而是从网格查询,因此我必须根据网格中的可用内容和可用方式进行调整。

2 个答案:

答案 0 :(得分:1)

我认为您没有正确定义条件。特别是,对于最后一个条件,您似乎想要最新的日期。

我会为此寻求窗口功能。我认为逻辑是:

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);

Here是db <>小提琴。

答案 1 :(得分:0)

我想出了一个在小提琴上尝试过的答案。不知道它是否可以在我的实际系统中运行(必须立即进行测试)。我不确定这是否是实现它的最佳/唯一方法。

select
distinct
concat(distinctTable.wrkCtrCd, '/', 
       distinctTable.prdntVrsnNum, '/', 
       distinctTable.matlNum, '/',
       case when countTable.cnt = 1 then min(distinctTable.ritmValFromDt)
       else max(distinctTable.parmVldFromDt)
       end
       ) as outputCol
from
(
  select
    tbl.prdntVrsnNum,
    tbl.matlNum,
    tbl.wrkCtrCd,
    count(*) as cnt
  from
    (select distinct * from mytable) as tbl
  group by
    tbl.prdntVrsnNum,
    tbl.matlNum,
    tbl.wrkCtrCd
) as countTable
inner join (select distinct * from mytable) as distinctTable
on countTable.prdntVrsnNum = distinctTable.prdntVrsnNum
and countTable.matlNum = distinctTable.matlNum
and countTable.wrkCtrCd = distinctTable.wrkCtrCd
group by
    distinctTable.prdntVrsnNum,
    distinctTable.matlNum,
    distinctTable.wrkCtrCd;

| outputCol                    |
| ---------------------------- |
| TO-HCH2/V001/96228/20180101  |
| TOU-A16/V003/197774/20181210 |