1

i have the following sql query to get an idea of what it does please read the description below

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

and the following sql tables

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
    +-----------------+------------+------------+

the reusltant datatable

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

idea is to sum the numitems column for products that have the same catalogid depinding on the data in the oitems table with the following conditions

  1. if ocardtype is empty then ignore the numitems and consider it as 0 in the sum and sum the ignored items to the ignoreditems column
  2. if ocardtype for some order is MasterCard or Visa and the odate is empty then ignore the numitems and consider it as 0 and sum the ignored items to the ignoreditems column
  3. if ocardtype is Paypal or Sofort, then just do the numitems sum without checking the odate because those types require no odate
  4. in another table called booked i have a column called ignoredoid, this columns contains orderids from the above table that i want to ignore even if the 3 conditions above are satsfied

To this point the query is working perfectly thanks to @Richard aka cyberkiwi to his answer in this question


The Question is, i need the result datatable to look like the following

+-----------+----------+--------------+-------------------+
| catalogid | numitems | ignoreditems | orderidcollection |
+-----------+----------+--------------+-------------------+
|       353 |        4 |            0 | O737,O739         |
|       364 |       10 |            0 | O738,O740         |
|       882 |        2 |            0 | O741              |
|       224 |        0 |            7 |                   |'O742 & O743 are ignored      
+-----------+----------+--------------+-------------------+

as you can see the only change is the addition of orderidcollection column, it have to add the orderid to the new column seperated by a comma only if that order is not ignored in the code, i've been googling for couple hours with no luck! is this even possible with SQL?

Community
  • 1
  • 1
user1570048
  • 880
  • 6
  • 35
  • 69
  • 2
    which database? The solutions for this can be database specific. – HLGEM Oct 01 '12 at 13:41
  • @HLGEM Microsoft SQL Server, and i am running this qury from vb.net and my experiance with sql is almost 0 – user1570048 Oct 01 '12 at 13:44
  • 1
    @user1570048, what version of SQL Server ? – Gabriele Petrioli Oct 01 '12 at 13:57
  • @GabyakaG.Petrioli microsoft sql server 2008 r2 – user1570048 Oct 01 '12 at 13:59
  • 2
    See http://stackoverflow.com/questions/7448734/sql-comma-separated-row-with-group-by-clause/7449137#7449137 and http://stackoverflow.com/questions/6344950/sql-query-to-get-aggregated-result-in-comma-seperators-along-with-group-by-colum/6348414#6348414 – Gabriele Petrioli Oct 01 '12 at 14:07
  • @GabyakaG.Petrioli thank you i manged to get this to work on other tables but i am not sure how to make it work with the above syntax, shall it be after then? when i put it after then i get syntax error as i said my knowledge in sql is very basic, i did it with linq but the sql syntax is confusing for me! – user1570048 Oct 01 '12 at 14:48
  • A similar question was asked here (http://stackoverflow.com/questions/12516346/updating-a-column-in-a-table-having-duplicate-rows). If you made your query into `view`, you could adapt the function in the provided link to cursor through the records in the view to build the comma separated list of values. If you give it a try and post what you've done, people will me more likely to help with the syntax. – James L. Oct 01 '12 at 15:45
  • @JamesL. i've tried for hours today to implement it with the above syntax with no luck – user1570048 Oct 01 '12 at 21:17
  • 1
    Please edit your question and add the SQL that you've tried today. Most people on SO are willing to help you, but not write the code for you. – James L. Oct 01 '12 at 21:46

1 Answers1

1

My Linq-to-Sql answer to your previous question extended to this one (LINQpad query):

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 _
         numitems = Sum(If(check, i.numitems, 0)), _
         ignoreditems = Sum(If(check, 0, i.numitems)), _
         group
         Select catalogid, numitems, ignoreditems, _
             orderidcollection = String.Join(",", (From g in group Where g.check Select g.i.orderid))
result.Dump

Note this solution issues multiple SQL queries to determine the orderids for each catalogid where check is True to accumulate each orderidcollection. There may be a more efficient solution (either using some, probably convoluted, Linq-to-Sql that causes the generated SQL to do the equivalent of String.Join, or get the catalogid, numitems, check, orderid using Linq-to-Sql and then use Linq-to-objects to do the final accumulations).

Note also this query includes your Booked table (with LINQpad's pluralisation).

Mark Hurd
  • 10,665
  • 10
  • 68
  • 101