Select within select with multiple matches on the other table SQL - sql

I have these 3 tables
Table 1:
id_Table1 field_table1_1 field_table1_2
1 A B
2 C D
3 E F
Table 1:
id_Table2 field_table2_1 field_table2_2
4 G H
5 I J
List item
Table 3:
id_Table3 id_Table1 id_Table2
1 1 4
2 1 5
3 2 5
So table 3 holds the relation between table 1 and 2.
What I want to do, is with a query, get all the fields in the table 1, plus one extra field that contains all the ids of the table 2 separated by coma.
So the result should be something like this:
id_Table1 field_table1_1 field_table1_2 id_Table2
1 A B 4, 5
2 C D 5
3 E F

One option use a lateral join and string_agg():
select t1.*, x.*
from table1 t1
outer apply (
select string_agg(t3.id_table2) id_table2
from table3 t3
where t3.id_table1 = t1.id_table1
) x
There is no need to bring table2 to get the results you want.

Related

Insert into new table an id with several values

I've been struggling with this problem.
I have 2 populated tables and a third empty one and I would like to populate the third with data from the other two. Correlate values
The idea is to assign every single ID from the 1st table to entries (several) found in the 2nd table that respect the condition where DestinedUserTypeID should be equal to UserTypeID),
Table 1
Id
UserName
UserTypeID
1
Bla
1
2
Ble
2
3
Bli
3
Table 2
ID
TaskName
DestinedUserTypeID
1
Task A
1
2
Task B
1
3
Task C
1
4
Task D
2
DESIRED TABLE, Table 3
ID
UserID
TaskID
1
1
1
2
1
2
3
1
3
...
Insert into Table3 ([UserId],[TaskID])
SELECT
Id,
(SELECT [Id] FROM [Table2] t2
WHERE [Id] <= 5 AND [DestinedUserTypeId] = 1)
FROM t1 WHERE [UserTypeId] = 1
Thank you!
You can do it with a simple join linked to your table 1 and 2 and just insert into your table3
SELECT
u.id,
t.id,
from
table1 as u inner join
table2 as t on u.userTypeId = t.DestinedUserTypeID

How SQL join work?

i am using MYSQL..
I have two tables:
TABLE 1 (TABLE NAME T1)
SL NAME
1 a
2 b
3 c
4 c
table 2 (table name T2)
SL NAME
1 a
2 c
3 c
4 c
Q1: how i count the total number of 'c' in both table?
Q2: which name is max occurrences in both table?
sl is primary key...
my query is:>
select count(*) from t1,t2
where t1.name=t2.name where t1.name='c';
but it showing 6
To count c in both tables you should use UNION, not JOIN.
Syntax:
SELECT ...
UNION [ALL | DISTINCT] SELECT ...
[UNION [ALL | DISTINCT] SELECT ...]
Doc:
http://dev.mysql.com/doc/refman/5.0/en/union.html
Edit:
I'll explain the query that you provided.
select count(*) from t1,t2 where t1.name=t2.name where t1.name='c';
First of all, you use WHERE clause twice which is a syntax error. Should be:
select count(*) from t1,t2 where t1.name=t2.name AND t1.name='c';
And this is the same that:
SELECT count(*) from t1
JOIN t2 ON t1.name=t2.name
WHERE t1.name='c';
You choose only rows with c value so these are the rows, that we will take under consideration:
TABLE 1 (TABLE NAME T1)
SL NAME
3 c
4 c
table 2 (table name T2)
SL NAME
2 c
3 c
4 c
Now, simple JOIN joins every row from table 1 to every row from table 2 (where condition is true of course)
So the result before counting is:
t1.SL t1.NAME t2.SL t2.NAME
3 c 2 c
4 c 3 c
3 c 4 c
4 c 2 c
3 c 3 c
4 c 4 c
This is 6 rows.
Answers for both of your questions.
SELECT name, count(*) as cnt
FROM(select t1.name from t1
union all
select name from t2) as tem
group by name
order by cnt DESC
This query will give you ranking of names ordered by occurrences.
To retrieve only c count, just add WHERE clause. To retrieve only the most occurring name set LIMIT clause to 1.
INSERT INTO #test
SELECT NAME FROM m_t1 WHERE NAME ='c'
UNION all
SELECT NAME FROM m_t2 WHERE NAME ='c'
SELECT count(*) FROM #test

Get ID pairs between 2 tables with matching child records

I have 2 tables with the same structure.
FIELD 1 INT
FIELD 2 VARCHAR(32) -- is a MD5 Hash
The query has to get matching FIELD 1 pairs from for records that have the exact combination of values for FIELD 2 in both TABLE 1 and TABLE 2.
These tables are pretty large ( 1 million records between the two ) but are deduced down to an ID and a Hash.
Example data:
TABLE 1
1 A
1 B
2 A
2 D
2 E
3 G
3 H
4 E
4 D
4 C
5 E
5 D
TABLE 2
8 A
8 B
9 E
9 D
9 C
10 F
11 G
11 H
12 B
12 D
13 A
13 B
14 E
14 A
The results of the query should be
8 1
9 4
11 3
13 1
I have tried creating a concatenated string of FIELD 2 using a correlated sub-query and FOR XML PATH string trick I read on here but that is very slow.
You can try following query also -
SELECT t_2.Field_1, t_1.Field_1 --1
FROM table_1 t_1, table_2 t_2 --2
WHERE t_1.Field_2 = t_2.Field_2 --3
GROUP BY t_1.Field_1, t_2.Field_1 --4
HAVING COUNT(*) = (SELECT COUNT(*) --5
FROM Table_1 t_1_1 --6
WHERE t_1_1.Field_1 = t_1.Field_1) --7
AND COUNT(*) = (SELECT COUNT(*) --8
FROM Table_2 t_2_1 --9
WHERE t_2_1.Field_1 =t_2.Field_1) --10
Edit
First the requested set of result is the combination of Field1 from both the tables where respective Field2 is exactly same.
so for that you can use one method which I have posted above.
Here
query will take the data from both the table based on field2 values (from line 1 to line 3)
then it will group the data based on field1 from table1 and field1 from table2 (line 4)
till this step you will get the result having field1 from table1 and field2 from table2 where it exists (at least one) matching based on field2 from tables for respective field1 values.
after this you just need to filter the result for correct (exactly same values for field2 values for respective field1 column value). so that you can make condition on row count.
here my assumption is that you don't have multiple values for field1 and field2 combination in either tables
means following rows will not be present -
1 b
1 b
In any of the tables.
if so, the rows count got for table1 and table2 for same field2 values should be match with the rows present in table1 for field1 and same rows only should present in tables2 for field2 value.
for this condition query has condition on count(*) in having clause (from line 5 to line 10).
Let me try to explain this version of the query:
select t1.field1 as t1field1, t2.field1 as t2field1
from (select t1.*,
count(*) over (partition by field1) as NumField2
from table1 t1
) t1 full outer join
(select t2.*,
count(*) over (partition by field1) as NumField2
from table2 t2
) t2
on t1.field2 = t2.field2
where t1.NumField2 = t2.NumField2
group by t1.Field1, t2.Field1
having count(t1.field2) = max(t1.NumField2) and
count(t2.field2) = max(t2.NumField2)
(which is here at SQLFiddle).
The idea is to compare the following counts for each pair of field1 values.
The number of field2 values on each.
The number of field2 values that they share.
All of these have to be equal.
Each subquery counts the number of values of field2 on each field1 value. For the first rows of your data, this produces:
1 A 2
1 B 2
2 A 3
2 D 3
2 E 3
. . .
And for the second table
8 A 2
8 B 2
9 E 3
9 D 3
9 C 3
Next, the full outer join is applied, requiring a match on both the count and the field2 value. This multiplies the data, producing rows such as:
1 A 2 8 A 2
1 B 2 8 B 2
2 A 3 NULL NULL NULL
2 D 3 9 D 3
2 E 3 9 E 3
NULL NULL NULL 9 C 3
And so on for all the possible combinations. Note that the NULLs appear due to the full outer join.
Note that when you have a pair, such as 1 and 8 that match, there are no rows with NULL values. When you have a pair with the same counts but they don't match, then you have NULL values. When you have a pair with different counts, they are filtered out by the where clause.
The filtering aggregation step applies these rules to get pairs that meet the first condition but not the second.
The having essentially removes any pair that has NULL values. When you count() a column, NULL values are not included. In that case, the count() on the column is fewer than the number of values expected (NumField2).

Left Join Where the right table has Having Count = 1

Table 1:
ID Values
1 1
2 2
3 3
4 4
Table 2:
ID Values
1 1
1 2
1 2
2 4
4 5
4 6
I need a result to be:
ID Table 1 Values Table 2 Values
1 1 1
2 2 4
3 3 *This is blank because Table 2 doesn't have ID 3
4 4 5
4 4 6
Notice the Exclusion of the rows in table 2 Where the Values are duplicated ( ID 1 and Value 2). Yet the 2 rows for ID 4 because both values from Table 2 for ID 4 do not have duplicity.
So this is a left join and I want only the Value from table 2 where that Value is not duplicated AND the ID matches an ID from Table 1.
Use a CTE over table 2, and then use that as the right side of your left join:
WITH t2 AS (
SELECT ID, Values FROM [Table 2]
GROUP BY ID, Values
HAVING COUNT(*) = 1
)
SELECT t1.ID, t1.Values [Table 1 Values], t2.Values [Table 2 Values]
FROM [Table 1] t1
LEFT JOIN t2 ON t1.ID = t2.ID

Merging columns in a join of two tables

I have the following tables in a Hive database:
table1:
id t X
1 1 a
1 4 a
2 5 a
3 10 a
table2:
id t Y
1 3 b
2 6 b
2 8 b
3 15 b
And I would like to merge them to have a table like:
id t Z
1 1 a
1 3 b
1 4 a
2 5 a
2 6 b
2 8 b
3 10 a
3 15 b
Basically what I want to do is :
a join on the column id (that part is easy)
merge the columns table1.t and table2.t into a new column t
have the variable Z that is equal to table1.X if the corresponding t comes from table1.t, and table2.Y if it comes from table2.t
order the table by id and then by t (that shouldn't be too hard)
I have no idea on how to do the parts 2 and 3. I tried with an outer join on
table1.id = table2.id and table1.t = table2.t, but it doesn't merge the two columns t.
Any pointer would be appreciated. Thanks!
CREATE TABLE table3 as SELECT * FROM (SELECT id,t,X as Z FROM t3_1 UNION ALL SELECT id,t,Y as Z FROM t3_2) u1 order by id,t;
Although not always required, using a subquery for the union'd queries help to organize, plus you can then reference the fields from the union (e.g. u1.id ) in other parts of the query.
You'll need the alias on the 3rd column to make the schemas match. If the source table name was not already a column, you could do something like this:
select * from (select id,t,'a' from t3_1 UNION ALL select id,t,'b' from t3_2) u1;
Try this one. It will insert in table 3, all the values from the other 2 tables
INSERT INTO table3 ( t, Z )
SELECT t, X
FROM table1
UNION ALL
SELECT t, Y
FROM table2