Group by on two tables and perform Left join on outcome VBA ADODB SQL Query - sql

I want to perform Group BY on two csv files and then perform Left Join on the outcome of both tables through VBA ADO Query in Excel. My end motive is to print the recordset.
Here is what I have done so far.
SELECT * FROM (
SELECT f1.[c3],
f1.[c4],
f1.[c5],
f1.[c6],
Sum(f1.[c8]) AS SUMDATA
FROM test1.csv F1
GROUP BY f1.[c3],
f1.[c4],
f1.[c5],
f1.[c6]) AS f3
LEFT JOIN SELECT * FROM (
SELECT f2.[c3],
f2.[c4],
f2.[c5],
f2.[c6],
Sum(f2.[c8]) AS SUMDATA
FROM test2.csv f2
GROUP BY f2.[c3],
f2.[c4],
f2.[c5],
f2.[c6]) AS f4
on f3.[c3]+ f3.[c4]+ f3.[c5]+ f3.[c6] = f4.[c3]+ f4.[c4]+ f4.[c5]+ f4.[c6]
WHERE f3.[SUMDATA] <> f4.[SUMDATA]
This shows a syntax error. How to implement this? Any help is much appreciated. TIA.
An update -
I manage to implement 1 LEFT JOIN and 2 GROUP BYs between 2 tables. As per the request, here are few details regarding my dataset.
It consists of fields - c1, c2 .... c8.
c8 is my target field.
My expected output - I do not need c7, c1 and c2 in output sheet. The info of c7, c1 and c2 is irrelevant. I need to do 5 things with my data.
Group Sum the c8 field based on c3, c4, c5 and c6 fields in CSV file 1 and store target field as SUMDATA
Group Sum the c8 field based on c3, c4, c5 and c6 fields in CSV file 2 and store target field as SUMDATA
Find the mismatched SUMDATA field entries between CSV1 and CSV2 (I used LEFT JOIN for this on concatenated c3, c4, c5, c6 fields)
Find the entries which are present in CSV1 but not in CSV2
Find the entries which are present in CSV2 but not in CSV1
Currently, I manage to write the code that works till step 3. I need to store the grouped tables temporarily which I got from Step 1 and 2, to perform the steps 4 and 5 which can be done through 2 more UNION, LEFT JOINs, and WHERE combination. This is where I am stuck right now.

This isn't really an answer but the formatting is important for readability.
It looks like there's a lot wrong with your SQL.
The syntax should look like this (assuming querying a csv works like you are thinking):
SELECT SUB1.Field1,
SUB1.AggField AS Agg1,
SUB2.AggField AS Agg2
FROM (SELECT Field1,
MAX(Field2) Agg_Field
FROM Table1 T1
GROUP
BY Field1
) SUB1
LEFT
JOIN (SELECT Field1,
MAX(Field2) Agg_Field
FROM Table1 T2
GROUP
BY Field1
) SUB2
ON SUB1.Field1 = SUB2.Field1
WHERE SUB1.AggField <> SUB2.AggField;
Also, you are missing a comma here: F1.[c5] F1.[c6] in the first chunk.
Try fixing the SQL syntax like this and see where that gets you.

Related

Filter a join based on multiple rows

I'm trying to write a query that filters a join based on several rows in another table. Hard to put it into words, so I'll provide a cut-back simple example.
Parent
Child
P1
C1
P1
C2
P1
C3
P2
C1
P2
C2
P2
C4
P3
C1
P3
C3
P3
C5
Essentially all rows are stored in the same table, however there is a ParentID allowing one item to link to another (parent) row.
The stored procedure is taking a comma delimited list of "child" codes, and based on whatever is in this list, I need to provide a list of potential siblings.
For example, if the comma delimited list was empty, the returned rows should be C1, C2, C3, C4, C5. If the list is "C2", the returned rows would be C1, C3, C4, and if the list is 'C1, C2', then the only returned row would be c3, c4.
Sample query:
SELECT [S].[ID]
FROM utItem [P]
INNER JOIN utItem [C]
ON [P].[ID] = [C].[ParentID]
INNER JOIN
(
-- Encapsulated to simplify sample.
SELECT [ID]
FROM udfListToRows( #ChildList )
GROUP BY
[ID]
) [DT]
ON [DT].[ID] = [C].[ID]
/*
In the event where I passed in "C2", this would work, it would return C1, C3, C4.
However this falls apart the moment there is more than 1 value in #ChildList. If I pass in "C2, C3", it would return siblings for either. But I only want siblings of BOTH.
**/
INNER JOIN [utItem] [S]
ON [C].[ParentID] = [S].[ParentID]
AND [C].[ID] <> [S].[ID]
WHERE
#ChildList IS NOT NULL
GROUP BY
[S].[ID]
UNION ALL
-- In the event that no #ChildList values are provided, return a full list of possible children (e.g. 1,2,3,4,5).
SELECT [C].[ID]
FROM [utItem] [P]
INNER JOIN [utItem] [C]
ON [P].[ID] = [C].[ParentID]
WHERE
#ChildList IS NULL
GROUP BY
[C].[ID]
Firstly, you can split your data into a table variable for ease of use
DECLARE #input TABLE (NodeId varchar(2));
INSERT #input (NodeId)
SELECT [ID]
FROM udfListToRows( #ChildList ); -- or STRING_SPLIT or whatever
Assuming you already had your data in a proper table variable (rather than a comma-separated list) you can do this
DECLARE #totalCount int = (SELECT COUNT(*) FROM #input);
SELECT DISTINCT
t.Child
FROM (
SELECT
t.Parent,
t.Child,
i.NodeId,
COUNT(i.NodeId) OVER (PARTITION BY t.Parent) matches
FROM YourTable t
LEFT JOIN #input i ON i.NodeId = t.Child
) t
WHERE t.matches = #totalCount
AND t.NodeId IS NULL;
db<>fiddle
This is a kind of relational division
Left-join the input to the main table
Using a window function, calculate how many matches you get per Parent
There must be at least as many matches as there are inputs
We take the distinct Child, excluding the original inputs

Access SQL - Is it possible to group by switch values?

Using Access 2010, I am trying to group by switch values and currently having trouble working out the code. Basically, within the treatment field in my DB, I have values such as D1, D2, D3, E1, E2, E3. The first letter denotes a particular treatment type e.g. D = Treatment1, E = Treatment2. I am looking to group the data by 'Treatment1' and 'Treatment2' for example.
SELECT switch(LEFT(t1.[treatment],1)='D',"Treatment1",LEFT(t1.[treatment],1)='E',"Treatment2"), count(t1.[UniqueID]) AS Total_Population, count(t2.[date]) AS DateSent, format(count(t2.[date]) / count(t1.[UniqueID]),"0.00%") AS Percentage_Sent, COUNT(IIF(t1.[requirements]='1',1,)) AS requirements_population
FROM Main_table AS t1 LEFT JOIN (SELECT t2.[ID], t2.[date] FROM Main_table AS t2 WHERE t2.date Not Like ('NA')) AS t2 ON t1.[ID] = t2.[ID]
GROUP BY [treatment]
Expected output is for example, Treatment1 - x amount, Treatment2 - y amount. However at present I get multiple rows of both Treatment1 & Treatment2 as the data behind those expressions is not unique (i.e. D1, D2, D3, E1, E2, E3).
Change to:
GROUP BY LEFT(t1.[treatment], 1)
so you group by the 1st letter of t1.[treatment] and not t1.[treatment]

How to get all Contract no against Leads in oracle sql query?

I need to create a sql query for below scenario:
Table name is remark
Columns are contractno and leadid.
1 contractno can have multiple leadid.
similarly,
1 leadid can assigned to multiple contractno.
Lets assume:
C1 --> L1
C2 --> L1, L2
C3 --> L2
I will get only one contractno i.e. C1 as parameter.
Now I have to find all Contracts against C1 through leadid.
Please help me out how I can achieve this.
Thank you.
SELECT r1.contractno
FROM remark r1
JOIN remark r2
ON r1.leadid = r2.leadid
WHERE r2.contractno = 'C1'
AND r1.contractno <> 'C1'
This assume your table has this format:
contractno leadid
C1 L1
C2 L1
C2 L2
C3 L1
If you dont, then you need to split the csv value into rows first:
Turning a Comma Separated string into individual rows
You can use a LISTAGG if you have to group list of contracts. Here too it is assumed that your table has linear format and not comma separated leadids
WITH cn
AS (SELECT DISTINCT leadid
FROM remark
WHERE contractno = 'C1')
SELECT Listagg(r.contractno, ',')
within GROUP (ORDER BY ROWNUM) contractno_C1
FROM remark r
join cn
ON r.leadid = cn.leadid
WHERE r.contractno <> 'C1'
GROUP BY cn.leadid;
http://sqlfiddle.com/#!4/54e48/1/0

SQL using same codes table for two different columns

I have a table (Foo) that has two columns that store a code value from a codes table:
id - code1 - code2
1 - CC - DD
The Codes table:
Name - Code - Grouping
Call Center - CC - 22
County - DD - 54
I need a SQL that will pull 'Call Center' and 'County' based on the first table. It is assumed that I know Foo.code1 necessarily uses Codes.Grouping=22 and Foo.code2 uses Codes.Grouping=54.
I'm trying to write one SQL that will return both values.
Try this query:
select name from codes c inner join foo f on c.code = f.code1 or c.code = f.code2
Here is sqlfiddle
I am not really sure if this is the answer to your question, because I don't know exactly what you mean. I guess however, that you want to get both codes and groupings for an id value of your Foo table. For this I would
SELECT Foo.id,
C1.Name AS code1_name, C1.Code AS code1_code,
C1.Grouping AS code1_grouping,
C2.Name AS code2_name, C2.Code AS code2_code,
C2.Grouping AS code2_grouping
FROM Foo
INNER JOIN Codes AS C1 ON C1.Code = Foo.code1
INNER JOIN Codes AS C2 ON C2.Code = Foo.code2
WHERE Foo.id = 1;
expanding tuffkid sqlfiddlesqlfiddle

SQL: How compare cells from different tables?

I have two tables - band and band2. Band:
and band2:
The columns are equals. I'm using Access 2010. I want to SELECT rows WHERE band.Kampas<>band2.Kampas, but there isn't primary key so I can't use JOIN operation.
Maybe someone has an idea?
The answer:
Only in these rows band.Kampas<>band2.Kampas.
Thanks in advance.
SELECT b2.*
FROM band2 b2
WHERE b2.kampas NOT IN (SELECT b1.kampas
FROM band b1
WHERE b1.kampas IS NOT NULL)
AND b2.kampas IS NOT NULL
If I understand you correctly this is what you want:
Select * from band where kampas not in (select kampas from band2)
union
Select * from band2 where kampas not in (select kampas from band)
EDIT. Ok, might be that not in doesn't work in Access. It looks like this could work, though:
Select * from band2 where not exists (select * from band where band.kampas = band2.kampas)
This find a selection in the inner select where kampas's match and we want to pick those band2 lines that returns an empty selection in the inner select.
If you want to do this two-way (i.e. also find from band) just use union like I did in the first attempt.
How about this:
select *
from Band as B1
inner join Band2 as B2
on B1.Stotis = B2.Stotis
where B1.Kampas <> B2.Kampas