I am attempting to do something using MSSQL that I believe is possible (easily) but I do not know how to vocalize the correct search string. I have the situation below.
Table A
UID | Value....
1 | a
2 | b
3 | c
Table B
PartTypes_uid_fk | Value....
1 | a
1 | b
1 | c
1 | d
1 | e
3 | 67
3 | 1354
I am attempting to get the following result, query Table A for all results {TableA.*} and on the same row result show the number of table b references {count TableB.tableA_fk}
What I have so far is the following.
SELECT DISTINCT t1.uid, CONVERT(varchar(MAX), t1.Name) AS Name, CONVERT(varchar(MAX), t1.Description) AS Description,
Count(t2.Items_uid_fk) OVER (Partition By t2.PartTypes_uid_fk) as Count
FROM [Table1] as t1 left outer join Table2 as t2 on t2.PartTypes_uid_fk=t1.uid;
This works for all of Table A records with an associated record in Table B but if there are 0 entries in Table B it won't work. The conversion of the varchars was required due to the fact they are ntext format and it was distinct.
Thank you for all your help in advance.
Stephen
Instead of running into problems with the GROUP BY on N/TEXT columns, and to run faster, you would want to pre-aggregate the B table and LEFT JOIN that against A.
select t1.*, ISNULL(t2.c, 0) AS CountOfB
from table1 t1
left join
(
select parttypes_uid_fk, count(*) c
from table2
group by parttypes_uid_fk
) t2 on t2.PartTypes_uid_fk=t1.uid
It's easier than that:
SELECT t1.uid, t1.Name, COUNT(*)
FROM [Table1] t1
LEFT JOIN [Table2] t2 ON t2.PartTypes_uid_fk = t1.uid
GROUP BY t1.uid, t1.Name
Your query should be
SELECT t1.uid,
CONVERT(varchar(MAX), t1.Name) AS Name,
CONVERT(varchar(MAX), t1.Description) AS Description,
Count(t2.Items_uid_fk) CountItems
FROM [Table1] as t1 left outer join Table2 as t2 on t1.uid = t2.PartTypes_uid_fk
GROUP BY uid, t1.name, t1.Description;
Related
I am trying to join the following two tables T1 and T2 on T1.id=T2.id, T1.MonA=T2.MonB such that
Whenever MonA=MonB (iow an entry can be found in both tables),
perform an ordinary join. This is the case for instace for ID A,
MonA=MonB=3
If a MonB entry is in table T2 but no equal MonA entry can be found in
Table T1, the join shall take from table T1 the row where MonA is
maximal. In the sample tables, this is the case for both last rows.
MonA from T1 which are not in T2 shall be ignored
The condition T1.id=T2.id is a necessary precondition, so this always needs to be true!
Table T1
ID MonA Data
A 2 BBB
A 3 CCC
B 4 DDD
B 5 EEE
B 11 EEE
Table T2
ID MonB Organ
A 3 Liver
B 5 Heart
B 7 Kidney
Here is, how the result should look like
ID MonA MonB Data Organ
A 3 3 CCC Liver
B 5 5 EEE Heart
B 11 7 EEE Kidney
I need this to be performed in Teradata SQL and honestly have no idea currently how to tackle the problem. Thanks for help!
EDIT: The may be several entries with identical ID, MonA=MonB, but different Data/Organ columns and i want all of them in the resulting table.
Lets do a join of t1 with t2 as follows
--gets all of the matching records by (id,mona) pairs from t1 with (id,monb) from t2
select a.id,a.mona,b.monb,a.data,b.organ
from t1 a
join t2 b
on a.id=b.id
and a.mona=b.monb
union all /*Here you want only from t2 not there in t1 by id*/
select b.id,x.mona,b.monb,x.data,b.organ
from t2 b
left join t1 a
on a.id=b.id
and a.mona=b.monb
left join (select row_number() over(partition by id order by mona desc) as rnk
,id
,mona
,data
from t1
)x
on b.id=x.id
and x.rnk=1 /*pick up only the largest values arranged by mona*/
where a.mona is null /*Gets only the missing records from t2 which are not in t1*/
This should return the expected result:
SELECT t1.id,t1.mona,t2.monb,t1.data,t2.organ
FROM t1
JOIN t2
ON t1.id=t2.id
QUALIFY
Row_Number()
Over (PARTITION BY t2.id, t2.organ
-- prefer same entry in both tables
ORDER BY CASE WHEN t1.mona = t2.monb THEN 1 ELSE 2 END
-- otherwise take max monA
,t1.mona DESC -- ) = 1
Could anyone help with how to take a single column:
ID
1
2
3
4
and show all possible distinct pairings in 2 columns:
ID ID
1 2
1 3
1 4
2 3
2 4
3 4
You can join the column on itself and arbitrarily decide that the left hand side will always be smaller than the right hand side (as the example shows):
SELECT t1.col, t2.col
FROM mytable t1
JOIN mytable t2 ON t1.col < t2.col
do self join
select t.id,t2.id from t t1 join t t2 on t.id<t1.id
A Simple Cartesian product should do
select distinct a.id as id_a, b.id as id_b
from test a, test b
where a.id<b.id;
Let's say i have:
Table1:
ID Name
1 Ann
2 Mike
3 Stan
4 Kyle
Table2:
Pair ID Person1ID Person2ID
1 1 2
2 3 4
I want to select pairs, but with names instead of IDs, so this would be the output:
1 Ann Mike
2 Stan Kyle
I imagine a simple:
inner join Table1 on Table1.ID=Table2.Person1ID
won't work, because I want both of them, not only one.
I'm pretty new to SQL so i'm sorry if there is a simple answer.
You have to join twice and use alias to diference the tables
SELECT t2.PairID, A.Name, B.Name
FROM Table2 t2
JOIN Table1 A
ON t2.Person1ID = A.ID
JOIN Table1 B
ON t2.Person2ID = B.ID
You can join sub query like below:
Select p.PairID, p.Name, q.Name
from
(Select t2.PairID, t1.Name
from Table1 t1 inner join Table2 t2
on t1.ID = t2.Person1ID) p
inner join
(Select t2.PairID, t1.Name
from Table1 t1 inner join Table2 t2
on t1.ID = t2.Person2ID) q
on p.PairID = q.PairID
See the result here in the demo.
I have two tables
Table 1:
color_id | label
---------|------
2 | 0
3 | 0
2 | 0
1 | 0
4 | 1
4 | 1
5 | 0
Table 2:
color_id
--------
2
1
4
I want a query that just gives me results for color_ids that are present in Table 2
So, I wrote:
SELECT *
FROM table1
LEFT JOIN table2
ON table1.color_id = table2.color_id
WHERE table2.color_id IS NOT NULL
however, the above gives duplicates as well. Meaning I get
2 | 0
2 | 0
1 | 0
4 | 1
4 | 1
I don't want the duplicates in the results. I just want unique items.
I want a query that just gives me results for color_ids that are present in Table 2
So, you shouldn't use LEFT JOIN in this case:
SELECT DISTINCT a.color_id, a.label
FROM table_1 a JOIN table_2 b
ON a.color_id = b.color_id
When you add the keyword Left (or Right or full) to a join specifier, you make the join an outer join. This means that you get all the rows from one side of the join, and only those rows from the other side that match. If you only want the rows from table_1 where the color_id is in table_2, then you want an inner join, specified by writing inner join or just writing join, without a left, right or full.
to eliminate duplicates, add the keyword distinct to the select clause...
Select distinct color_id, label
From table1 t1
join table2 t2
on t2.color_id = t1.color_id
Try the below query
SELECT DISTINCT color_id
FROM table_1 T1
WHERE EXISTS (SELECT 1 FROM table_2 T2 where T1.color_id = T2.color_id)
Use an inner join and a distinct clause:
SELECT DISTINCT table1.color_id, table1.label
FROM table1
INNER JOIN table2
ON table1.color_id = table2.color_id
What you are looking for is an INNER JOIN combined with a
SELECT distinct table1.color_id, tabl1.label
FROM table1
INNER JOIN table2 ON table1.color_id = table2.color_id
This eliminates any item in table1 not present in table 2 and duplicated rows.
the reason of that is you used Left Join, which will keep all obs in table1.
Try this:
SELECT table1.* FROM table1 Inner JOIN table2 ON table1.color_id = table2.color_id
this should works as actually all table2 obs are in table1. To be more serious, if table2 has obs that are not in table1 and you do want to keep them, replace inner join with right join.
I have one complicated question. I'll try to explain it with example:
have one table that have primary key, and I want to join other table there the first's table primary key is foreign key, and I want If in the second table there is duplicate foreign key to select the number of repeatability. For example:
1-st table:
id name
--- -----
1 Greg
2 Alan
3 George
4 John
5 Peter
2-nd table
id aid data
--- ----- -------
1 2 CCCV
2 2 VVVV
3 3 DDDDD
4 3 SSSS
5 4 PPPPP
I want the result of the join to be:
id(1st table) aid name Data Number
----------- ---- ----- ----- -----
1 null Greg null 1
2 1 Alan CCCV 1
2 2 Alan VVVV 2
3 3 George DDDDD 1
3 4 George SSSS 2
4 5 John PPPPP 1
5 null Peter null 1
I searched a lot, I couldn't find anything. Maybe I do not know how search, or there is no such thing as what I want to do.
SELECT Table1.id, Table2.id as aid, Table1.name, Table2.data,
GREATEST(1, (SELECT COUNT(*)
FROM Table2 t2
WHERE t2.aid = Table1.id
AND t2.id <= Table2.id))
AS number
FROM Table1
LEFT JOIN Table2
ON Table2.aid = Table1.id
ORDER BY id, aid;
works in both MySQL and PostgreSQL.
As per my comment, you've tagged this both MySQL and PostgreSQL.
This answer is for PostgreSQL.
SELECT
table1.id,
table2.aid,
table1.name,
table2.data,
ROW_NUMBER() OVER (PARTITION BY table1.id ORDER BY table2.aid) AS number
FROM
table1
LEFT JOIN
table2
ON table1.id = table2.aid
Queries for PostgreSQL 8.3 which has no window functions.
With bigger tables it is regularly much faster to use a JOIN instead of a correlated sub-query.
The first query aggregates values for Table2 before joining to Table1, which should befaster, too:
SELECT t1.id, t2.aid, t1.name, t2.data, COALESCE(t2.ct, 1) AS number
FROM Table1 t1
LEFT JOIN (
SELECT x.aid, x.data, count(y.aid) + 1 AS ct
FROM Table2 x
LEFT JOIN Table2 y ON x.aid = y.aid AND x.id > y.id
GROUP BY x.aid, x.data
) t2 ON t2.aid = t1.id
ORDER BY t1.id, t2.ct;
And ORDER BY should be fixed.
Alternative without sub-query. Might be faster, yet:
SELECT t1.id, t2.aid, t1.name, t2.data, count(*) + count(t3.id) AS number
FROM Table1 t1
LEFT JOIN Table2 t2 ON t2.aid = t1.id
LEFT JOIN Table2 t3 ON t3.aid = t2.aid AND t3.id < t2.id
GROUP BY t1.id, t2.aid, t1.name, t2.data
ORDER BY t1.id, count(t3.id);
Not sure, didn't test with a bigger set. Test performance with EXPLAIN ANALYZE. Could you report back your results?