why 9 rows are fetch from this query? - sql

Given 2 tables T1 and T2.
T1 T2
A 1
B 2
C 3
You make a query SELECT * FROM T1, T2.
What is the no: of rows that are fetched from this query?
Answer is 9

This query results in cartesian product because no other conditions are provided. Every row from first table is matched with every row from second table.
The result is
A 1
A 2
A 3
B 1
B 2
B 3
C 1
C 2
C 3

Because each record from the first table is returned along with each record of the second table and the result is not filtered.
The exact output will be:
T1 T2
A 1
A 2
A 3
B 1
B 2
B 3
C 1
C 2
C 3
(order may vary)

It is a cartesian product: select all rows from one table (3) and all rows from another table (3) and combine them, so 3*3=9.

That's what you asked it to do. You got all the rows from T1 and all the rows from T2. They don't just get added together -- that won't work if the columns are different, for example, though you can do this with UNION -- they get merged in what's known as a "cartesian product". You essentially get all combinations of rows from both tables. And 3*3 = 9.

Related

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;

Get row counts for different lookup values

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.

sqlite delete all results where column a and column b is not in first n items

Lets say I have the following table
a b c
-----------
1 1 5
1 2 3
4 1 2
1 2 4
4 2 10
And I want to delete all rows where none of the first n rows has the same value in a and b as that row.
So for example the resulting tables for various n's would be
n = 1
a b c
-----------
1 1 5
// No row other than the first has a 1 in a, and a 1 in b
n = 2
a b c
-----------
1 1 5
1 2 3
1 2 4
// The fourth row has the same values in a and b as the second, so it is not deleted. The first 2 rows of course match themselves so are not deleted
n = 3
a b c
-----------
1 1 5
1 2 3
4 1 2
1 2 4
// The fourth row has the same values in a and b as the second, so it is not deleted. The first 3 rows of course match themselves so are not deleted
n = 4
a b c
-----------
1 1 5
1 2 3
4 1 2
1 2 4
// The first 4 rows of course match themselves so are not deleted. The fifth row does not have the same value in both a and b as any of the first 4 rows, so is deleted.
I've been trying to work out how to do this using a not in or a not exists, but since I'm interested in two columns matching not just 1 or the whole record, I'm struggling.
Since you are not defining a specific order, the result is not completely defined, but depends on arbitrary choices of implementation regarding which rows are computed first in the limit clause. A different SQLite version for example may give you a different result. With that being said, I believe that you want the following query:
select t1.* from table1 t1,
(select distinct t2.a, t2.b from table1 t2 limit N) tabledist
where t1.a=tabledist.a and t1.b=tabledist.b;
where you should replace N with the desired number of rows
EDIT: So, to delete directly from the existing table you need something like:
with toremove(a, b, c) as
(select * from table1 tt
EXCEPT select t1.* from table1 t1,
(select distinct t2.a, t2.b from table1 t2 limit N) tabledist
where t1.a=tabledist.a and t1.b=tabledist.b)
delete from table1 where exists
(select * from toremove
where table1.a=toremove.a and table1.b=toremove.b and table1.c=toremove.c);

Get rows with single values using SQlite

By using SQlite, I'd like to get all rows that show in a specific column only one single distinct value. Like from following table:
A B
1 2
2 1
3 2
4 3
5 1
6 1
7 2
8 4
9 2
Here I'd like to get only row Nr. 4 an 8 as there values (3 and 4) occur only once in the entire column.
You could use a query like this:
SELECT *
FROM mytable
WHERE B IN (SELECT B FROM mytable GROUP BY B HAVING COUNT(DISTINCT A)=1)
Please see fiddle here.
Subquery will return all B values that are present only once (you could also use HAVING COUNT(*)=1 in this case), the outer query will return all rows where B is returned by the subquery.

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.