SQL add processed ids to a single cell seperated with a comma - sql

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
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
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
if ocardtype is Paypal or Sofort, then just do the numitems sum
without checking the odate because those types require no odate
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?

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

Related

ms access 2000: Too few parameters with DSum

I have this problem for like an hour now and I just can't find the solution through Google, so maybe someone here can help me?
I have this table here:
|--------------------------|
| Table1 |
| Product | Amount | Buyer |
|--------------------------|
| Food | 4 | 1 |
| Paper | 30 | 1 |
| Food | 2 | 2 |
|--------------------------|
And I want to have this table here:
|-------------------|
| table2 |
| Buyer | Purchases |
|-------------------|
| 1 | 34 |
| 2 | 2 |
|-------------------|
Before the code is executed, table2 looks like this:
|-------------------|
| table2 |
| Buyer | Purchases |
|-------------------|
| 1 | |
| 2 | |
|-------------------|
The code I tried is:
UPDATE table2
SET Purchases = (
DSum("Amount", "table1", "table1.Buyer = " & table2.Buyer)
)
However, I get the following error:
Too few parameters. Expected 1
If I remove the last part of the DSum method:
UPDATE table2
SET Purchases = (
DSum("Amount", "table1")
)
I don't get an error. What did I do wrong?
Don't include the table names:
UPDATE
table2
SET
Purchases = DSum("Amount", "table1", "Buyer = " & Buyer & "")
No single quotes as Buyer is a number.

How to get count of instances in a one to many relationship across multiple tables?

I have a query where I am attempting to find multiple instances of a custtype for a specific date. The following query works fine as is:
select idm, count(*) totals
from customer.purch a
where exists (select null
from customer.name b
where b.idad = a.id
and custdate = to_date('5/11/2017', 'MM/DD/YYYY')
and custtype = 'R'
)
group by idm
having count(*) > 1;
The issue I am having however, is I am not sure how to expand the above query to find different combinations of custtype on the given date. For example, how can i get the query to give me the idm of a record where at least one custype is R and at least one other custype is 'Z'? I figure a self join on the customer.name field might be the correct way to go, but I am not sure how to implement it. Thank you for your time.
Sample Data
Table customer.purch a
_______________
|idm | id |
| 1 | 896 |
| 2 | 207 |
| 3 | 359 |
________________
Table customer.name b
______________________________
|idad | custdate |custtype|
| 896 | 5/11/2017 | R |
| 896 | 5/11/2017 | Z |
| 207 | 5/11/2017 | R |
| 207 | 5/11/2017 | X |
| 359 | 5/11/2017 | R |
| 359 | 5/11/2017 | Z |
| 359 | 5/11/2017 | R |
| 359 | 5/11/2017 | R |
_______________________________
Output
______________
|IDM | count |
| 1 | 2 |
| 3 | 4 |
_______________
If I understand correctly, you can use aggregation and a having clause:
select p.idm, count(*) totals
from customer.purch p join
customer.name n
on p.id = n.idad
where n.custdate = date '2017-05-11'
group by p.idm
having sum(case when n.custtype = 'R' then 1 else 0 end) > 0 and
sum(case when n.custtype = 'Z' then 1 else 0 end) > 0;

MS Access SQL - Aggregate Count with 2 Example Table

I have a situation where I need to query from a 2 table in MS Access.
I'm new to this SQL access.
Table: UserInfo
===================
| UserID | Gender |
===================
| K01 | M |
| K02 | M |
| K03 | F |
| K04 | M |
===================
Table: OrderInfo
===================================
| OrderID | Type | UserID_FK |
===================================
| 1 | Food | K01 |
| 2 | Food | K01 |
| 3 | Toolkit | K02 |
| 4 | Food | K04 |
| 5 | Toolkit | K03 |
===================================
The question is:
I want to query so the result produce this table, how can I do it in MS Access?
I'm thinking that I should do a subquery but I don't know how to do it.
Table: Summary
================================================================
| UserID | Gender | CountOfToolkit | CountOfFood | TotalCount |
================================================================
| K01 | M | 0 | 2 | 2 |
| K02 | M | 1 | 0 | 1 |
| K03 | F | 1 | 0 | 1 |
| K04 | M | 0 | 1 | 1 |
================================================================
First, Type is a reserved word in MS Access.
You should avoid using reserved words.
Having said that, try this:
SELECT a.UserID, a.Gender, SUM(IIF(b.[Type] ='Food',1,0)) AS CountOfFood, SUM(IIF(b.[Type] ='Toolkit',1,0)) AS CountOfToolkit, COUNT(*) AS TotalCount
FROM UserInfo a INNER JOIN OrderInfo b ON a.UserId = b.UserID_FK
GROUP BY a.UserID, a.Gender
This crosstab query doesn't rely on having just Food & Toolkit as your types - it will count any new types you add.
The NZ wrapped around the Count(sType) ensures the 0 values are shown, while the CLNG ensures it's still treated as a number rather than text.
You could just use Count(sType) AS CountOfType.
TRANSFORM CLNG(NZ(Count(sType),0)) AS CountOfType
SELECT UserID
,Gender
,COUNT(sType) AS TotalCount
FROM UserInfo LEFT JOIN OrderInfo ON UserInfo.UserID = OrderInfo.UserID_FK
GROUP BY UserID, Gender
PIVOT sType

No rowid or key need most recent row

I am trying my hardest to get a list of the most recent rows by date in a DB2 file. The file has no unique id, so I am trying to get the entries by matching a set of columns. I need DESCGA most importantly as that changes often. When it does they keep another row for historical reasons.
SELECT B.COGA, B.COMSUBGA, B.ACCTGA, B.PRFXGA, B.DESCGA
FROM mylib.myfile B
WHERE
(
SELECT COUNT(*)
FROM
(
SELECT A.COGA,A.COMSUBGA,A.ACCTGA,A.PRFXGA,MAX(A.DATEGA) AS EDATE
FROM mylib.myfile A
GROUP BY A.COGA, A.COMSUBGA, A.ACCTGA, A.PRFXGA
) T
WHERE
(B.ACCTGA = T.ACCTGA AND
B.COGA = T.COGA AND
B.COMSUBGA = T.COMSUBGA AND
B.PRFXGA = T.PRFXGA AND
B.DATEGA = T.EDATE)
) > 1
This is what I am trying and so far I get 0 results.
If I remove
B.ACCTGA = T.ACCTGA AND
It will return results (of course wrong).
I am using ODBC in VS 2013 to structure this query.
I have a table with the following
| a | b | descri | date |
-----------------------------
| 1 | 0 | string | 20140102 |
| 2 | 1 | string | 20140103 |
| 1 | 1 | string | 20140101 |
| 1 | 1 | string | 20150101 |
| 1 | 0 | string | 20150102 |
| 2 | 1 | string | 20150103 |
| 1 | 1 | string | 20150103 |
and i need
| 1 | 0 | string | 20150102 |
| 2 | 1 | string | 20150103 |
| 1 | 1 | string | 20150103 |
You can use row_number():
select t.*
from (select t.*,
row_number() over (partition by a, b order by date desc) as seqnum
from mylib.myfile t
) t
where seqnum = 1;

select from table between dates and count duplicates

I have a table named tblOrders
| ID | name | email | amount | date |
+-----+---------+------------+---------+------------+
| 1 | danny | dan#email | $10.00 | 06/01/2015 |
| 2 | bryan | bra#email | $50.00 | 06/01/2015 |
| 3 | jenny | jen#email | $20.00 | 06/02/2015 |
| 4 | gabby | gab#email | $35.00 | 06/02/2015 |
| 5 | lisa | lisa#email | $12.00 | 06/03/2015 |
| 6 | don | don#email | $23.00 | 06/04/2015 |
| 7 | danny | dan#email | $22.00 | 06/04/2015 |
| 8 | bryan | bra#email | $55.00 | 06/05/2015 |
| 9 | danny | dan#email | $69.00 | 06/20/2015 |
| 10 | danny | dan#email | $49.00 | 06/25/2015 |
I want to select from tblOrders between date 06/03/2015 and 06/25/03/2015
and then count the number of repeated customers I have.
Select between date 06/03/2015 and 06/25/03/2015 provides
| ID | name | email | amount | date |
+----+-------+------------+--------+-------------+
| 5 | lisa | lisa#email | $12.00 | 06/03/2015 |
| 6 | don | don#email | $23.00 | 06/04/2015 |
| 7 | danny | dan#email | $22.00 | 06/04/2015 |
| 8 | bryan | bra#email | $55.00 | 06/05/2015 |
| 9 | danny | dan#email | $69.00 | 06/20/2015 |
| 10 | danny | dan#email | $49.00 | 06/25/2015 |
Then checking by email from those records if exist in all tblOrders and count
This should provide count of 2 as there are 2 customers between those dates that ordered before.
How can I achieve that with one SQL query?
I'm using Access database and ASP classic
My current code is
ReturnCustomers = 0
Set rs = Server.CreateObject("ADODB.Recordset")
SQL = ("select ID,Email,OrderDate from tblOrders Where OrderDate between #"&date1&"# and "&date2&";")
rs.Open SQL,Cnn,3,1
Do while Not rs.EOF
Set rsCount = Server.CreateObject("ADODB.Recordset")
SQL = ("select ID from tblOrders Where Email='"&rs("Email")&"' and Not ID="&rs("ID")&";")
rsCount.Open SQL,Cnn,3,1
IF Not rsCount.EOF Then
ReturnCustomers = ReturnCustomers+1
End IF
rsCount.Close
Set rsCount = Nothing
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
response.write ReturnCustomers
How can I do this one in 1 SQL query?
It seems you want repeat customers --- those who made a purchase during the target date range and also made a purchase sometime before the start of that date range.
First create a query to retrieve those unique customers:
SELECT DISTINCT o1.email
FROM
tblOrders AS o1
INNER JOIN tblOrders AS o2
ON o1.email = o2.email
WHERE
(o1.date Between #2015-6-3# And #2015-6-25#)
AND o2.date < #2015-6-3#;
However you actually want only the count of those customers. So you can use the first query as a subquery and derive the count from that:
SELECT Count(sub.email) AS CountOfemail
FROM
(
SELECT DISTINCT o1.email
FROM
tblOrders AS o1
INNER JOIN tblOrders AS o2
ON o1.email = o2.email
WHERE
(o1.date Between #2015-6-3# And #2015-6-25#)
AND o2.date < #2015-6-3#
) AS sub;
you are not looking for duplicates. If you want to find out who ordered between date #06/03/2015# to #06/25/03/2015# and ordered before #06/03/2015# , your query should be like :
select distinct name, email from tblorders o
where date >=#06/03/2015# and date < #06/25/03/2015#
and exists (select * from tblorders p where p.email = o.email
and p.date <#06/03/2015# )
Also please specify your sql system.