SQL Query with two tables - sql

I have two tables as following
Point: ListMember:
index description indexParent indexChild
-------------------- ---------------------------
1 ABC 333 1
2 DEF 333 2
3 GHI 444 1
333 Hello 444 2
444 Bye 444 3
555 Welcome
An example of result table that i am looking for
Result:
Index description listSize descriptionChild
333 Hello 2 ABC
333 Hello 2 DEF
444 Bye 3 ABC
444 Bye 3 DEF
444 Bye 3 GHI
555 Welcome 0
I am new to database and still learning SQL so i am not quite sure how to do the select to obtain the result i am looking for.

Assuming your results should be 333 Hello. You have to do two left joins (for 555 with no children).
psuedo code:
Select p.index, p.description, p2.index as listsize, p2.description as descriptionchild
from point p
left join listmember l
on p.index = l.indexparent
left join point p2
on l.indexchild = p2.index

Due to using the unfortunate column name index, you have to include brackets every time you refer to that column. This is working for me:
SELECT P.[index] AS [Index],
P.description,
(SELECT COUNT(*) FROM ListMember WHERE indexParent = P.[index]) AS listSize,
P2.description AS descriptionChild
FROM Point P
LEFT JOIN ListMember LM ON LM.indexParent = P.[index]
LEFT JOIN Point P2 ON P2.[index] = LM.indexChild
WHERE P.[index] NOT IN (SELECT indexChild FROM ListMember)
ORDER BY P.[index]

I do believe the following query should work for you (SQL Fiddle):
SELECT p1.[index], p1.description,
(
SELECT COUNT(1)
FROM ListMember ls
WHERE ls.indexParent = p1.[index]
) AS listSize,
p2.description AS descriptionChild
FROM Point p1
LEFT JOIN ListMember l ON l.indexParent = p1.[index]
LEFT JOIN Point p2 ON l.indexChild = p2.[index]
WHERE p1.[index] NOT IN
(
SELECT indexChild FROM ListMember
)

Related

SQL query for the below expected output

I have 2 tables
TABLE1
ASSET OWNER1 OWNER2
-----------------------
note 111 444
pen 333 555
book 222 666
TABLE2
OWNER NAME
-------------
111 Avani
444 Jack
333 Jyothi
555 John
222 Nilehi
666 Mohit
What should be SQL query to get the following output?
ASSET OWNER1 NAME OWNER2 NAME
------------------------------------
note 111 Avani 444 Jack
pen 333 Jyothi 555 John
book 222 Nilehi 666 Mohit
I tried following query but the records of ASSET column are being repeated
SELECT DISTINCT(TABLE1.ARREST), TABLE1.OWNER1, TABLE2.NAME, TABLE1.OWNER2, TABLE2.NAME FROM TABLE1 JOIN TABLE2 ON
TABLE1.OWNER1 = TABLE2.OWNER OR TABLE1.OWNER2 = TABLE2.OWNER
Join the same table twice, with different aliases.
For example:
select
a.asset,
a.owner1,
b.name,
a.owner2,
c.name
from table1 a
left join table2 b on a.owner1 = b.owner
left join table2 c on a.owner2 = c.owner
You need two separate JOINs:
SELECT T1.ARREST, T1.OWNER1, T2_1.NAME, T1.OWNER2, T2_1.NAME
FROM TABLE1 T1 JOIN
TABLE2 T2_1
ON t1.OWNER1 = T2_1.OWNER JOIN
TABLE2 T2_2
ON T1.OWNER2 = T2_2.OWNER;
Often you would use LEFT JOINs for this, in case one of the columns is empty.

How to Join with select top

I have a problem with the combination of multiple tables.
My SQL query:
SELECT *
FROM CRM.Bank as a
JOIN CRM.Documents as b ON a.Bank_ID = b.Documents_ID
JOIN CRM.Counterparties as c ON c.Counterparties_ID = b.Documents_ID
JOIN CRM.Items as d ON d.Document_tran_ID = b.Documents_ID
I have table CRM.Items, which has the following columns:
Item_ID Document_tran_ID Name
======= ================ ====
1 1 Advertising banner
2 1 Shipping costs
3 2 Garden tent
4 2 Additional fasteners
5 2 Shipping costs
And now I have a problem how to connect only the first items to the document (d.Document_tran_ID = b.Documents_ID ) ??
I know I should use SELECT TOP. However, I have a problem with creating the correct query
Expect the result in the form of:
Bank_ID Documents_ID Counterparties_ID Document_tran_ID Name
======= ============ ================= ================ ====
22 1 4 1 Advertising banner
23 2 20 2 Garden tent
24 3 21 3 Other
Only the first Item from the document is matched.
I think you can try to use CROSS APPLY join. In the inner query, you can apply order condition for selecting TOP row
SELECT *
FROM CRM.Bank as a
JOIN CRM.Documents as b ON a.Bank_ID = b.Documents_ID
JOIN CRM.Counterparties as c ON c.Counterparties_ID = b.Documents_ID
CROSS APPLY
(select top 1 * from CRM.Items i where i.Document_tran_ID = b.Documents_ID) as d
use sub-query for documents table
SELECT *
FROM CRM.Bank as a
JOIN ( select min(Document_tran_ID) as Documents_ID from CRM.Documents) as b ON a.Bank_ID = b.Documents_ID
JOIN CRM.Counterparties as c ON c.Counterparties_ID = b.Documents_ID
JOIN CRM.Items as d ON d.Document_tran_ID = b.Documents_ID

SQL query- help in implementation

I have two tables: Member and Document
Member table:
Memberkey(Key) Member country
-------------- ---------------
111 Aus
222 US
333 Germany
444 Chile
Document table:
Memberkey(notNULL) doc_type_cd doc_cat_cd docname
---------------- ----------- ---------- -------------
111 1 1 Sales_doc
222 2 1 Finance_doc
222 3 3 Legal_doc
333 3 3 Legal_doc
444 2 1 Finance doc
444 3 3 Legal_doc
My requirement is to fetch memberkey, member country, and doc_name only if the document is legal_doc (i.e. doc_type_cd = 3 and doc_cat_cd =3). If no such document exists for a member, then this should come as null.
Output:
Memberkey member country doc_name
---------- -------------- -----------
111 aus NULL
222 US Legal_doc
333 Germany Legal_doc
444 Chile Legal_doc
How can I achieve this? If I use condition on doc_type_cd and doc_cat_cd in the query, then those members will be skipped, who have no legal_doc (111 in this example). Also, if a member has no entry in "document" table, then it should also be shown with member key, country and documentname(NULL in this case). Is there any effcient way to achieve this?
Please help. Thanks!
You need a left join for your requirement. By left joining on the three conditions below you will get a record for every member, and if they do have a legal document than that will be populated in the doc_name column, and if they do not have a legal document than the value will be null.
SELECT M.MemberKey, M.[member country], D.doc_name
FROM Member M
LEFT JOIN Document D ON
M.MemberKey = D.MemberKey AND
D.doc_type_cd = 3 AND
D.doc_cat_cd = 3
Here is a solution in MSSQL:
SELECT
M.MemberKey
, M.MemberCountry
, DCA.DocName
FROM
[Member] M
OUTER APPLY (
SELECT
D.DocName
FROM
[Document] D
WHERE
D.MemberKey = M.MemberKey
AND D.doc_type_cd = 3
AND D.doc_cat_cd =3
) DCA
Please note, that this query will retrieve multiple rows if there are multiple legal documents. If you want to get the first document, add TOP(1) to the subquery.
You want to use a case statement, and test for doc_type_cd or doc_cat_cd, like this:
select memberkey,
[member country],
case when doc_type_cd = 3 or doc_cat_cd = 3 then doc_name else null end
from memberTable mt
left outer join documentTable dt
on mt.memberKey = dt.memberKey
Here is another solution which could run on most RDBMS:
-- Query to get all members with legal document
SELECT
M.MemberKey
, M.MemberCountry
, D.DocName
FROM
Member M
INNER JOIN Document D
ON M.MemberKey = D.MemberKey
WHERE
D.doc_type_cd = 3
AND D.doc_cat_cd =3
UNION ALL
-- Query to get all members without legal document
SELECT
M.MemberKey
, M.MemberCountry
, NULL AS DocName
FROM
Member M
WHERE
NOT EXISTS (SELECT 1 FROM Document D WHERE D.MemberKey = M.MemberKey AND D.doc_type_cd = 3 AND D.doc_cat_cd = 3)

Multiple case merge sql

I have two datasets a and b each with fields for cusip and ticker. The sql i'd like to perform would take a column from set b if a.cusip=b.cusip, but if i cannot find a match for the cusip, i'd like to take the column from b if a.ticker=b.ticker.
Is there an easy way to execute this? I'm having trouble constructing the code in one go.
Inner join and Or in your where Clause condition should do the job.
Select * from a
inner join b on a.cusip=b.cusip
or a.ticket = b.ticket;
You'll need to join to your B table twice, once on cusip and once on ticker. Then you can use coalesce to take the first non-null value.
select
coalesce (b_cusip.column, b_ticker.column),
...
from
a
left outer join b b_cusip
on a.cusip = b_cusip.cusip
left outer join b b_ticker
on a.ticker = b_ticker.ticker
You could try something like this:
data dataset_a;
input cusip ticker;
datalines;
1 111
2 222
3 333
5 555
;
run;
data dataset_b;
input cusip ticker value;
datalines;
1 111 10
20 222 25
30 333 40
4 444 55
;
run;
proc sql _method;
create table mydata as
select
a.*
,b.value
from dataset_a as a
left join dataset_b as b
on (case
when a.cusip=b.cusip then 1
when a.ticker=b.ticker then 1
else 0
end)=1
;
quit;
returns:
cusip ticker value
1 111 10
2 222 25
3 333 40
5 555 .

Subquery or two joins

I have three tables:
tbl_trans
trans_id volume
a 10
b 20
c 30
tbl_primary_id
trans_id primary_id
a QQQ
b b
c RRR
tbl_name
trans_id name
a Billy
QQQ Tom
b Lizzy
RRR Peter
I need to join the name column from tbl_name to tbl_trans. A straight inner join won't work because I need primary_id as an intermediary to return this:
trans_id tbl_name.trans_id volume name
a QQQ 10 Tom
a QQQ 10 Billy
b b 20 Lizzy
c RRR 30 Peter
What's the best way to do this? I was using a subquery but wasn't sure if there was a more direct statement.
(Side note: None of this is my schema. I can't modify the design in any way, unfortunately.)
just 2 joins
select tt.trans_id, tn.trans_id, tt.volume, tn.name
from tbl_trans tt
inner join tbl_primary_id tti on tti.trans_id = tt.trans_id
inner join tbl_name tn on tn.trans_id = tti.primary_id
by the way, your column naming is a little bit weird : primary_id in tbl_primary_id is related with trans_id in tbl_name
oh, seems I missed something :
select tt.trans_id as tid, tti.primary_id as tid2, tt.volume, tn.name
from tbl_trans tt
inner join tbl_primary_id tti on tti.trans_id = tt.trans_id
inner join tbl_name tn on tn.trans_id = tti.primary_id or tn.trans_id = tti.trans_id
see sqlfiddle