Get row counts for different lookup values - sql

A temp table has 700+ records with a PK. 12 columns contain Id values from lookup tables. Each lookup table has 4-8 records in it. How can I get a record count for each Id value in table LookupA that has a relationship via the PK to Id values in every other lookup table? Each lookup value in each lookup table needs to compared for a record count to every other lookup table and value.
I can write a SQL statement to get specific values for specific columns, but that's a long exercise and will slow down the proc.
Here's a sample of the data.
PK LookupA LookupB LookupC
1 1 1 3
2 1 2 3
3 1 3 2
4 2 4 2
5 4 1 1
6 3 2 1
7 2 3 3
8 4 4 3
9 4 3 2
10 1 1 2
The results need to compare LookupA with LookupB and LookupC to get a row count.
Table Value LookupB 1 2 3 4 LookupC 1 2 3
LookupA 1 2 1 1 0 0 2 2
2 0 0 1 1 0 1 1
3 0 1 0 0 1 0 0
4 1 0 1 1 1 1 1
Then LookupB would be compared to LookupA and LookupC.
And LookupC would be compared to LookupA and LookupB.

With this code you can get the numbers for all combinations of A,B and C in pairs:
select 'A-B' as Combination, LookupA, LookupB, count(*) as NumRecords
from table
group by Combination,LookupA, LookupB
UNION
select 'A-C' as Combination, LookupA, LookupC, count(*) as NumRecords
from table
group by Combination,LookupA, LookupC
UNION
select 'B-C' as Combination, LookupB, LookupC, count(*) as NumRecords
from table
group by Combination,LookupB, LookupC
After this, if you want to see all the values for LookupA comparing to B and C just
look for Combinations A-B and A-C

If I understand correctly, your temp table contains foreign keys to other tables, so why not simply use joins? Something like this.
SELECT COUNT(DISTINCT lookupA.id) as CountA
, COUNT(DISTINCT lookupB.id) as CountB
, etc...
FROM #temp_table t
LEFT OUTER JOIN lookupA a on a.id = t.lookupA
LEFT OUTER JOIN lookupB b on b.id = t.lookupB
...etc
I would suggest reviewing the design if possible. Having so many small tables complicates things, is it not possible to consolidate this and just have one lookup table? You could have an additional field "LookupType" and all the lookups could be in the same place which would make retrieval much simpler.

I used a slight derivative of the statement below without any UNIONs to get me where I wanted to go.
/*
select 'A-B' as Combination, LookupA, LookupB, count(*) as NumRecords
from table
group by Combination, LookupA, LookupB
*/
I used a variable and a WHILE loop to place the various summaries where they need to be.

Related

Create a table with unknown columns SQL

I have a table that looks like this
ID
Steps
Letters
1
1
a
1
2
e
1
3
b
2
1
c
2
2
d
3
1
b
3
2
a
And a query that consists of the output
a
b
d
My goal is to create a table/ modify the first one to get rid of the letter column, and instead, have N additional columns (where N is the number of rows in the second query above) and the output is 1 if the last step for that ID was that specific letter, 0 if that letter was in any step, and NULL if it never was. Making a table like this
ID
a
b
d
1
0
1
NULL
2
NULL
NULL
1
3
1
0
NULL
I assume pivoting makes sense as a way to approach it, but I don't even know where to begin

How to check how many times a record is repeated in different tables

I have two tables here:
Table 1:
process_id customer_id
16 1
21 1
22 1
Table 2:
process_id customer_id
16 1
16 1
22 1
I would like to check how many times each row in table 1 is repeated in table 2.
For example, row 1 in table 1 is repeated 2 times in table 2, row 2 repeated 0 times and row 3 repeated 1 time. I'm not sure how to loop through each row in table 1 and get this result.
As I understood, this is what you are asking for:
select table1.process_id,table1.customer_id,count(table2.process_id) as table2count
from table1 left outer join table2 on table1.process_id==table2.process_id and table1.customer_id=table2.customer_id
group by table1.process_id,table1.customer_id;

How to use a new column as a flag to show Null row?

I have table A:
id
1
2
3
4
5
and table B:
id
2
3
4
I left join A and B:
id id
1 NULL
2 2
3 3
4 4
5 NULL
And how can I get a new column like this:
id id flag
1 NULL 0
2 2 1
3 3 1
4 4 1
5 NULL 0
Generally speaking, I want all rows in A but not in B to be flaged as 0 and want all rows in both tables to be flaged as 1. How can I achieve that? Better not use CTE.
This is just a CASE expression:
CASE WHEN B.id IS NULL THEN 0 ELSE 1 END AS flag
Alternatively, you could use an IIF (which is shorthand CASE expression):
IIF(b.id IS NULL, 0,1)
I would recommend using exists:
select a.*,
(case when exists (select 1 from b where b.id = a.id
then 1 else 0
end) as flag
from a;
The purpose of using exists instead of left join is that you are guaranteed to not get duplicate rows -- even if ids are duplicated in b. That is a nice guarantee.
From a performance perspective, the two should be similar, but it is possible that the case is an iota faster.

Create multiple rows based on 1 column

I currently have a table with a quantity in it.
ID Code Quantity
1 A 1
2 B 3
3 C 2
4 D 1
Is there anyway to write a sql statement that would get me
ID Code Quantity
1 A 1
2 B 1
2 B 1
2 B 1
3 C 1
3 C 1
4 D 1
I need to break out the quantity and have that many number of rows
Thanks
Here's one option using a numbers table to join to:
with numberstable as (
select 1 AS Number
union all
select Number + 1 from numberstable where Number<100
)
select t.id, t.code, 1
from yourtable t
join numberstable n on t.quantity >= n.number
order by t.id
Online Demo
Please note, depending on which database you are using, this may not be the correct approach to creating the numbers table. This works in most databases supporting common table expressions. But the key to the answer is the join and the on criteria.
One way would be to generate an array with X elements (where X is the quantity). So for rows
ID Code Quantity
1 A 1
2 B 3
3 C 2
you would get
ID Code Quantity ArrayVar
1 A 1 [1]
2 B 3 [1,2,3]
3 C 2 [2]
using a sequence function (e.g, in PrestoDB, sequence(start, stop) -> array(bigint))
Then, unnest the array, so for each ID, you get a X rows, and set the quantity to 1. Not sure what SQL distribution you're using, but this should work!
You can use connect by statement to cross join tables in order to get your desired output.
check my solution it works pretty robust.
select
"ID",
"Code",
1 QUANTITY
from Table1, table(cast(multiset
(select level from dual
connect by level <= Table1."Quantity") as sys.OdciNumberList));

Multiple columns from a table into one, large column?

I don't know what in the world is the best way to go about this. I have a very large array of columns, each one with 1-25 rows associated with it. I need to be able to combine all into one large column, skipping blanks if at all possible. Is this something that Access can do?
a b c d e f g h
3 0 1 1 1 1 1 5
3 5 6 8 8 3 5
1 1 2 2 1 5
4 4 2 1 1 5
1 5
there are no blanks within each column, but each column has a different number of numbers in it. they need to be added from left to right so a,b, c, d, e, f. And the 0 from be needs to be in the first blank cell after the second 3 in A. And the first 5 in H needs to be directly after the 1 in g, with no blanks.
So you want a result like:
3
3
0
5
1
4
1
6
1
4
etc?
Here is how I would approach the problem. Insert your array into a work table with an autonumber column (important to retain the order the data is in, databases do not guarnatee an order unless you can give them something to sort on) called id
as well as the array columns.
Create a final table with an autonumber column (see above note on why you need an automnumber) and the column you want as you final table.
Run a separate insert statment for each column in your work table and run them in the order you want the data.
so the inserts would look something like:
insert table2 (colA)
select columnA from table1 order by id
insert table2 (colA)
select columnB from table1 order by id
insert table2 (colA)
select columnC from table1 order by id
Now when you do select columnA from table2 order by id you should have the results you need.