SQL Server case when和min与max的组合[已关闭]

bmp9r5qi  于 2022-11-28  发布在  其他
关注(0)|答案(1)|浏览(225)

已关闭。此问题需要details or clarity。当前不接受答案。
**想要改进此问题吗?**通过editing this post添加详细信息并阐明问题。

昨天关门了。
Improve this question
我有一个查询会产生这样数据集:

CIF_NO           ORGAZ_NO RETAIL_INT_RT int_rt   st_cd
---------------- -------- ------------- -------- -----
2013000250018117 002      60.000000     0.016780 00001
1125820000000868 001      21.000000     0.009080 00004
1000000000185544 001      21.000000     0.019610 00004
2013000250018117 002      60.000000     0.021140 00004
1125820000000868 001      21.000000     NULL     NULL
1000000000185544 001      21.000000     NULL     NULL
1125820000000868 001      21.000000     NULL     NULL
1000000000185544 001      21.000000     NULL     NULL
1125820000000868 001      24.000000     NULL     NULL

来自以下查询:

select a.CIF_NO, a.ORGAZ_NO, a.RETAIL_INT_RT, b.int_rt, b.st_cd 
  from card_data a
       left join card_trx b on a.CARD_NO = b.card_no

我想要的是这样的东西:

CIF_NO           ORGAZ_NO RETAIL_INT_RT int_rt   st_cd
---------------- -------- ------------- -------- -----
2013000250018117 002      60.000000     0.016780 00001
1000000000185544 001      21.000000     NULL     NULL
1125820000000868 001      24.000000     NULL     NULL

应用的逻辑如下:

  • 检查是否组织编号=“001”,然后获取最大值(零售_INT_RT)
  • 检查是否ORGAZ_NO = '002',然后
  • 检查st_cd是否=“00001”,然后获取最大值(int_rt),否则获取最大值(RETAIL_INT_RT)
  • 如果st_cd具有2个以上的值,则显示具有min(st_cd)的行。

如何在没有辅助查询或嵌套查询的情况下,使用最小值和最大值的组合来应用这种使用case的逻辑?
我试过这个:

select j.cif_no, 
       max(j.retail_int_rt) as retail_int_rt, 
       max(j.int_rt) as int_rt, 
       j.ORGAZ_NO, 
       min(j.ST_CD) as st_cd 
from 
(
    SELECT h.CIF_NO,
           max(cast(h.RETAIL_INT_RT as FLOAT)) retail_int_rt,
           max(cast(i.INT_RT*12*100 as FLOAT)) int_rt,
           h.ORGAZ_NO,
           isnull(min(i.st_cd),'00000') ST_CD
    FROM  card_data h
          LEFT JOIN card_trx i on h.card_no = i.card_no
    group by h.CIF_NO, h.ORGAZ_NO, i.ST_CD
) j
left join 
(
     SELECT l.CIF_NO,
            l.orgaz_no,
            isnull(min(m.st_cd),'00000') ST_CD
     FROM   card_data l
            LEFT JOIN card_trx m on l.card_no = m.card_no
     group by l.CIF_NO, l.orgaz_no
) k on j.CIF_no   = k.CIF_NO 
   and j.ST_CD    = k.ST_CD 
   and j.orgaz_no = k.orgaz_no
group by j.CIF_NO, j.ORGAZ_NO

有好几个条件不满足,这一个也试过了:

select j.* 
from 
(
    SELECT h.CIF_NO,
           max(cast(h.RETAIL_INT_RT as FLOAT)) retail_int_rt,
           max(cast(i.INT_RT*12*100 as FLOAT)) int_rt,
           h.ORGAZ_NO,
           isnull(min(i.st_cd),'00000') ST_CD
    FROM   card_data h
           LEFT JOIN card_trx i on h.card_no = i.card_no
    group by h.CIF_NO, h.ORGAZ_NO, i.ST_CD
) j
join 
(
    SELECT l.CIF_NO,
           l.orgaz_no,
           isnull(min(m.st_cd),'00000') ST_CD
    FROM   card_data l
           LEFT JOIN card_trx m on l.card_no = m.card_no
    group by l.CIF_NO, l.orgaz_no
) k on j.CIF_no   = k.CIF_NO 
   and j.ST_CD    = k.ST_CD 
   and j.orgaz_no = k.orgaz_no

它接近我的期望,但仍然没有得到我所期望的条件。

fslejnso

fslejnso1#

示例数据设置:

select identity(int, 1, 1) as [Id], t.*
into #s
from (values
('2013000250018117', '002', 60.000000, 0.016780, '00001'),
('1125820000000868', '001', 21.000000, 0.009080, '00004'),
('1000000000185544', '001', 21.000000, 0.019610, '00004'),
('2013000250018117', '002', 60.000000, 0.021140, '00004'),
('1125820000000868', '001', 21.000000, NULL, NULL),
('1000000000185544', '001', 21.000000, NULL, NULL),
('1125820000000868', '001', 21.000000, NULL, NULL),
('1000000000185544', '001', 21.000000, NULL, NULL),
('1125820000000868', '001', 24.000000, NULL, NULL)
) t (CIF_NO, ORGAZ_NO, RETAIL_INT_RT, int_rt, st_cd);

添加identity列是为了更容易地跟踪行的原始顺序。它没有任何其他用途,可以安全地删除。
鉴于这种设置,下面是对您的问题的答案完全按照您的措辞(加上一些我不得不从您的代码中闪烁出来的东西):

with cte as (
    select s.Id, s.CIF_NO, s.ORGAZ_NO, s.RETAIL_INT_RT, s.int_rt, s.st_cd,
        max(s.RETAIL_INT_RT) over(partition by s.CIF_NO, s.ORGAZ_NO, s.st_cd) as [MaxRetail],
        max(s.int_rt) over(partition by s.CIF_NO, s.ORGAZ_NO, s.st_cd) as [MaxInt],
        st.CountSt,
        min(isnull(s.st_cd, '')) over(partition by s.CIF_NO, s.ORGAZ_NO) as [MinSt]
    from #s s
        cross apply (
            -- Had to make a separate subquery as DISTINCT is incompatible with OVER
            select count(distinct isnull(cd.st_cd, 'No such value')) as [CountSt]
            from #s cd
            where cd.CIF_NO = s.CIF_NO and cd.ORGAZ_NO = s.ORGAZ_NO
        ) st
)
select t.Id, t.CIF_NO, t.ORGAZ_NO, t.RETAIL_INT_RT, t.int_rt, t.st_cd
from (
    select c.Id, c.CIF_NO, c.ORGAZ_NO, c.RETAIL_INT_RT, c.int_rt, c.st_cd,
        case
            -- check if ORGAZ_NO = '001' then get max(RETAIL_INT_RT)
            when c.ORGAZ_NO = '001' and c.MaxRetail = c.RETAIL_INT_RT then 1
            -- check if ORGAZ_NO = '002' then
            when c.ORGAZ_NO = '002' then case
                -- check if st_cd = '00001' then get max(int_rt)
                when c.CountSt = 1 and c.st_cd = '00001' and c.int_rt = c.MaxInt then 1
                -- else get max(RETAIL_INT_RT)
                when c.CountSt = 1 and c.st_cd != '00001' and c.RETAIL_INT_RT = c.MaxRetail then 1
                -- if st_cd has more than 2 values, the rows with min(st_cd) are shown
                when c.CountSt > 2 and isnull(c.st_cd, '') = c.MinSt then 1
            end
            else 0
        end as [SelectionCriteria]
    from cte c
) t
where t.SelectionCriteria = 1
order by t.Id;

如果你运行它,你会发现结果和你所说的期望有很大的不同。为什么?因为你就是这样写你的需求的。
要想得到有用的答案,首先要把问题写得尽可能精确,如果你不能用简单明了的英语表达自己,那么,无论出于什么原因,同样不擅长表达的人,就很难猜对。
关于这一点:
而不需要辅助查询或嵌套查询?
--据我所知,这是不可能的。不过,你可能指的是别的什么,所以没关系。

相关问题