【问题标题】:SQL Select caseSQL 选择案例
【发布时间】:2012-10-01 06:47:48
【问题描述】:

我有以下 sql 表

oitems table

    +---------+-----------+----------+
    | orderid | catalogid | numitems |
    +---------+-----------+----------+
    | O737    |       353 |        1 |
    | O738    |       364 |        4 |
    | O739    |       353 |        3 |
    | O740    |       364 |        6 |
    | O741    |       882 |        2 |
    | O742    |       224 |        5 |
    | O743    |       224 |        2 |
    +---------+-----------+----------+

Orders table
+-----------------+------------+------------+
|         orderid | ocardtype  |   odate    |
+-----------------+------------+------------+
|     O737        | Paypal     |            | 'OK
|     O738        | MasterCard | 01.02.2012 | 'OK
|     O739        | MasterCard | 02.02.2012 | 'OK
|     O740        | Visa       | 03.02.2012 | 'OK
|     O741        | Sofort     |            | 'OK
|     O742        |            |            | 'ignore because ocardtype is empty
|     O743        | MasterCard |            | 'ignore because Mastercard no odate
+-----------------+------------+------------+

名为result的reusltant数据表

 +-----------+----------+--------------+
| catalogid | numitems | ignoreditems |
+-----------+----------+--------------+
|       353 |        4 |            0 |
|       364 |       10 |            0 |
|       882 |        2 |            0 |
|       224 |        0 |            7 |
+-----------+----------+--------------+

想法是对具有相同catalogid 的产品的numitems 列求和,具体取决于oitems 表中的数据,条件如下

  1. 如果ocardtype 为空,则忽略numitems 并考虑它 作为 0 在 sum 和 sum 忽略的项目到 ignoreditems
  2. 如果某个订单的ocardtypeMasterCardVisa 并且 odate 为空然后忽略 numitems 并将其视为 0 并将忽略的项目汇总到 ignoreditems
  3. 如果ocardtypePaypalSofort,那么只需执行numitems 和 不检查日期,因为这些类型不需要odate

基本上我想将结果数据表保存到临时数据表并将其加载到 vb.net 数据表中

我很难弄清楚如何在 sql 查询中执行此操作!我需要这个作为 vb.net 的 sql 命令,能够使用循环和大量检查的 vb.net 数据表以编程方式完成它 使用 linq 是一种选择,但我只需要从服务器获取它

【问题讨论】:

    标签: sql vb.net


    【解决方案1】:
    select catalogid, numitems, allitems - numitems ignoreditems
    from (
      select i.catalogid,
        sum(case when (ocardtype in ('PayPal','Sofort') OR
                       ocardtype in ('mastercard','visa') and
                       odate is not null) AND NOT EXISTS (
                         select * from booked b
                         where b.ignoredoid = o.orderid
                       ) then numitems
                       else 0 end) numitems,
        sum(numitems) allitems
      from orders o
      join oitems i on i.orderid=o.orderid
      group by i.catalogid
    ) X
    

    【讨论】:

    • OP 将 ocardtypeodate 都称为可能是“空的” - 但是您已经将 one 的情况解释为“空字符串” ",在另一个中为 "NULL"。 (啊哈,我看到了偷偷摸摸的编辑:-))
    • @Damien - 当我想同时排除 NULL 和 '' 时,我使用 col > ''。因为它简单且有效。但是,是的,因为它很容易落入 ELSE,所以我已经把它去掉了。
    • @Richard aka cyberkiwi 请再做一件事,在另一个名为 booked 的表中,我有一个名为 ignoredoid 的列,此列包含上表中的 orderids,即使条件条件我也想忽略上面是对的,那我该怎么做,比如WHERE orderid does not exist in column ignoredoid of table booked
    • @Richard aka cyberkiwi 非常感谢,sql 真的很酷,我应该开始学习它!
    • @Richard aka cyberkiwi 你好,我已经更新了问题,你能检查最后一部分吗?
    【解决方案2】:

    类似:

    SELECT
         oi.catalog_id,
         SUM(CASE
                WHEN ocardtype in ('Paypal','Sofort') THEN numitems
                WHEN ocardtype in ('Mastercard','Visa') and odate is not null THEN numitems
                ELSE 0 END) as numitems,
         SUM(CASE
                WHEN ocardtype is null then numitems
                WHEN ocardtype in ('Mastercard','Visa') and odate is null THEN numitems
                ELSE 0 END) as ignoreditems
    FROM
       oitems oi
          inner join
       Orders o
          on
             oi.orderid = o.orderid
    GROUP BY
       oi.catalog_id
    

    (假设您在叙述中使用了“空”一词,则表示该列是NULL

    【讨论】:

    • 为了逻辑我会-1,但我会让它通过。看起来 OP 希望这 2 个总和是互补的,但无论我怎么看,在某些情况下它们不会加起来。
    【解决方案3】:

    这是您原始请求的 Linq-to-sql 版本(作为 LINQpad 查询):

    Dim odateRequired = {"MasterCard", "Visa"}
    Dim odateNotRequired = {"Paypal", "Sofort"}
    Dim result = From o In Orders Join i In Oitems On o.orderid Equals i.orderid _
                 Let check = o.ocardtype IsNot Nothing _
                         AndAlso ((odateRequired.Contains(o.ocardtype) _
                                   AndAlso o.odate IsNot Nothing) _
                            OrElse odateNotRequired.Contains(o.ocardtype)) _
             Group By i.catalogid Into _
             numitem = Sum(If(check, i.numitems, 0)), _
             ignored = Sum(If(check, 0, i.numitems))
    
    result.Dump
    

    您在 cmets 中对 RichardTheKiwi 的回答的额外要求(它只包括 check 前面的 Not (From b In Bookeds Where b.ignoredoid=i.orderid).Any AndAlso):

    Dim odateRequired = {"MasterCard", "Visa"}
    Dim odateNotRequired = {"Paypal", "Sofort"}
    Dim result = From o In Orders Join i In Oitems On o.orderid Equals i.orderid _
                 Let check = Not (From b In Bookeds Where b.ignoredoid = i.orderid).Any _
                         AndAlso o.ocardtype IsNot Nothing _
                         AndAlso ((odateRequired.Contains(o.ocardtype) _
                                   AndAlso o.odate IsNot Nothing) _
                            OrElse odateNotRequired.Contains(o.ocardtype)) _
             Group By i.catalogid Into _
             numitem = Sum(If(check, i.numitems, 0)), _
             ignored = Sum(If(check, 0, i.numitems))
    
    result.Dump
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-29
      • 1970-01-01
      • 2023-04-11
      • 2022-01-20
      • 2014-12-12
      • 1970-01-01
      • 1970-01-01
      • 2021-08-12
      相关资源
      最近更新 更多