SQL Join and integer condition in jointure to make them relative - sql

i already submit my problem but without example it was not clear enough so here is the tables :
Users
id_user / key_user
1 / 123FDADA21312QD
2 / 994GFCS4595433D
Companies
id_company / key_company
1 / 3123123123
2 / 5435345454
Products
id_product / id_company_product / code_product
1 / 1 / iphone
2 / 1 / iBook
3 / 1 / macbook
Tyds
id_tyd / user_tyd / product_tyd
1 / 1 / 1 -- mean that the id_user = 1 made a line for the iphone
sold by the company 1
2 / 1 / 2 -- same : user 1 for the ibook of company 1
Here is my request :
SELECT
products.id_product,
users.id_user,
COALESCE(id_tyd, 'NONE') AS id_tyd
FROM tyds
INNER JOIN users
ON tyds.user_tyd = users.id_user
INNER JOIN products
ON tyds.product_tyd = products.id_product
INNER JOIN companies
ON products.id_company_product = companies.id_company
WHERE users.key_user = '123FDADA21312QD'
AND companies.module_key_company = '3123123123'
AND products.cancelled_product >= 0
AND products.code_product = 'iphone'
That will return
products.id_product = 1
users.id_user = 1
tyds.id_tyd = 1
Perfect. But what i'd like to do is getting the users.id_user EVEN IF there is no records for this user in tyds. Like :
SELECT
products.id_product,
users.id_user,
COALESCE(id_tyd, 'NONE') AS id_tyd
FROM tyds
INNER JOIN users
ON tyds.user_tyd = users.id_user
INNER JOIN products
ON tyds.product_tyd = products.id_product
INNER JOIN companies
ON products.id_company_product = companies.id_company
WHERE users.key_user = '123FDADA21312QD'
AND companies.module_key_company = '3123123123'
AND products.cancelled_product >= 0
AND products.code_product = 'macbook'
I'd like to get :
products.id_product = 3
users.id_user = 1
tyds.id_tyd = NONE
Because at this step, i'm sure that the product i ask exists and the user_key exist. But i'm not sure that there is matching records in tyds and that is what i want to test.
Of course, all the tables are simplify and i'll need more datas but i think this will make my point.
My first move was to put the WHERE condition in the JOIN match but, don't know why, if i put the products.code_product in the products jointure, it give me tyds records even for different id_product...
Thanks a lot for your help !

if that's the case, change the join from INNER JOIN to LEFT JOIN. INNER JOIN, basically returns rows that are present (atleast one match) on all tables being joined, while LEFT JOIN returns rows on the lefthand side even without matching records on the other tables.
Query,
SELECT c.*, d.id_tyd
FROM
(
SELECT a.id_user, b.id_product
FROM users a CROSS JOIN products b
) c
LEFT JOIN tyds d
ON d.user_tyd = c.id_user AND
d.product_tyd = c.id_product
LEFT JOIN products e
ON e.id_product = c.id_product
LEFT JOIN companies f
ON e.id_company_product = f.id_company
LEFT JOIN users g
ON c.id_user = g.id_user
WHERE e.code_product = 'macbook' AND
f.key_company = '3123123123' AND
g.key_user = '123FDADA21312QD'
SQLFiddle Demo

Related

Select statement where joins causing records to be excluded

I have the below query with multiple joins.The last 3 joins are required to get the g.fin_id value. This works fine (see results) BUT because some records in the ACCUM_ISS_CHAR_HIST table have e.char9_nme values of NULL, it excludes the records in the results altogether. So it seems as when the e.char9_nme value has a record then it will produce a result, but as soon as it has a Null value then it is excluded. I would still like to see the records even though the g.fin_id for those will then be blank because they have a e.char9_nme value of Null. How can I change the query to accomplish this?
select
a.acct_id,
c.fld3_txt,
b.issue_loc1_cde,
b.instr_id,
a.fld1_nme,
b.issue_cls2_nme,
g.fin_id,
e.char9_nme
from position_dg as a
inner join
infoportal..issue_dg as b on b.INSTR_ID = a.INSTR_ID
inner join
InfoPortal..IVW_ACCT as c on a.acct_id = c.acct_id
inner join
InfoPortal..DW_AcctCharDG as d on a.acct_id = d.acctid
inner join
ACCUM_ISS_CHAR_HIST as e on a.instr_id = e.instr_id
inner join
MD_FINANCIAL_ENTITY as f on e.char9_nme = f.fin_enty_name
inner join md_FINANCIAL_ENTITY_ALTERNATE_IDENTIFIER as g on
f.fin_enty_id = g.fin_enty_id
and b.MAT_EXP_DTE > getdate()
and b.issue_cls1_nme = 'Derivatives'
and a.as_of_tms >= getdate()-1
and b.iss_typ in ('FFX','IRS','EQF')
and d.AcctChrSetId = 'DerivativeRpt'
and d.EndTms IS NULL
and a.acct_id = 'FOGEMBLCR'
and g.id_ctxt_typ = 'LEGAL_ENTITY_IDENTIFIER'
and e.as_of_dte = (
select MAX (as_of_dte)-1
from accum_iss_char_hist
)
I expect the results to show fin_id records for some ond blank fin_id records for some, but at the moment only the ones with a fin_id record is hown and the rest is excluded from the results.
You are looking for a left join.
Join all those tables (last 3 as you said) as left join. For better clarity I have moved conditions of every tables in their ON clause and for base table a made a where clause.
select
a.acct_id,
c.fld3_txt,
b.issue_loc1_cde,
b.instr_id,
a.fld1_nme,
b.issue_cls2_nme,
g.fin_id,
e.char9_nme
from position_dg as a
inner join
infoportal..issue_dg as b on b.INSTR_ID = a.INSTR_ID
and b.MAT_EXP_DTE > getdate()
and b.issue_cls1_nme = 'Derivatives'
and b.iss_typ in ('FFX','IRS','EQF')
inner join
InfoPortal..IVW_ACCT as c on a.acct_id = c.acct_id
inner join
InfoPortal..DW_AcctCharDG as d on a.acct_id = d.acctid
and d.AcctChrSetId = 'DerivativeRpt'
and d.EndTms IS NULL
left join
ACCUM_ISS_CHAR_HIST as e on a.instr_id = e.instr_id
and e.as_of_dte = (
select MAX (as_of_dte)-1
from accum_iss_char_hist
)
left join
MD_FINANCIAL_ENTITY as f on e.char9_nme = f.fin_enty_name
left join
md_FINANCIAL_ENTITY_ALTERNATE_IDENTIFIER as g on f.fin_enty_id = g.fin_enty_id
and g.id_ctxt_typ = 'LEGAL_ENTITY_IDENTIFIER'
Where a.as_of_tms >= getdate()-1
and a.acct_id = 'FOGEMBLCR'

SQL Subquery - Repeat Where Clause?

I know this is a 101 question, but do I need to repeat the Where clause in the main query in the sub-query below? It appears to give me the same either way, but is it even needed?
FROM account a
LEFT JOIN account pa ON a.parentaccountid = pa.accountid
JOIN customeraddress ca ON a.accountid = ca.parentid
JOIN optionsetmetadata osm ON osm.entityname = 'customeraddress'
AND osm.optionsetname = 'addresstypecode'
AND ca.addresstypecode = osm.[option]
LEFT JOIN sik_warehouse w ON a.sik_warehouseid = w.sik_warehouseid
LEFT JOIN sik_deliverymethods dm ON a.sik_deliverymethodid = dm.sik_deliverymethodsid
WHERE a.accountnumber IN ('58398',
'4350',
'5076',
'4310',
'15847')
AND Addresstypecode = 2
AND ca.jms_status = 100000000
AND ca.addressnumber > (
SELECT TOP 1 ca_sub1.addressnumber
FROM customeraddress ca_sub1
JOIN account a_sub1 ON ca_sub1.parentid = a_sub1.accountid
AND ca_sub1.addressnumber > 2
order by ca_sub1.addressnumber ASC
add inline view if you want to put multiple where condition.

Postgresql select related tags (many to many)

I have a VIEW named review, which is related to a cars table, and the cars table have a many to many relationship with table tags (through join table named cars_tags), but what I need is retrieve the reviews from the cars which are related with some tags, AND at same time related to another tags. What I have today is the following SQL code:
SELECT "cars"."review".*
FROM "cars"."review"
LEFT JOIN cars.cars ON (cars.review.car_id = cars.cars.id)
LEFT JOIN cars.makes ON (cars.cars.make_id = cars.makes.id)
LEFT JOIN cars.cars_tags ON (cars.cars.id = cars.cars_tags.car_id)
LEFT JOIN cars.tags ON (cars.cars_tags.tag_id = cars.tags.id)
WHERE (cars.tags.id IN ('91782e95-8c5d-4254-82ab-b11a21306c18'))
AND (cars.tags.id IN ('031cec30-df27-471e-858d-53c3d9657c8a'))
ORDER BY "cars"."review"."score" DESC LIMIT 100
This SQL brings me NO results, but I am sure that there are cars which are related to first id:'91782e95-8c5d-4254-82ab-b11a21306c18'AND '031cec30-df27-471e-858d-53c3d9657c8a' at same time.
What am I doing wrong?
bool_or
select r.col1, r.col2
from
cars.review r
left join
cars.cars on r.car_id = cars.id
inner join
cars.cars_tags on cars.id = cars_tags.car_id
inner join
cars.tags on cars_tags.tag_id = tags.id
group by r.col1, r.col2
having
bool_or (tags.id = '91782e95-8c5d-4254-82ab-b11a21306c18')
and
bool_or (tags.id = '031cec30-df27-471e-858d-53c3d9657c8a')
order by r.score desc
limit 100
exists version:
select col1, col2
from cars.review
where exists (
select 1
from
cars.cars
inner join
cars.cars_tags on cars.id = cars_tags.car_id
inner join
cars.tags on cars_tags.tag_id = tags.id
where review.car_id = cars.id
group by 1
having
bool_or (tags.id = '91782e95-8c5d-4254-82ab-b11a21306c18')
and
bool_or (tags.id = '031cec30-df27-471e-858d-53c3d9657c8a')
)
order by score desc
limit 100
From what I understand you're interested in reviews for a car that has 2 specific tags.
This can be done with the query below. I've removed the reference to cars.make as you weren't retrieving any data from it. Also I've removed the reference to cars.tags as the only information you were using was the tag id which is in the cars_tags table.
SELECT "cars"."review".*
FROM "cars"."review"
WHERE
EXISTS (SELECT * FROM cars.cars_tags
WHERE cars.cars_tags.car_id = cars.review.cars_id
AND cars.cars_tags.tag_id = '91782e95-8c5d-4254-82ab-b11a21306c18')
AND
EXISTS (SELECT * FROM cars.cars_tags
WHERE cars.cars_tags.car_id = cars.review.cars_id
AND cars.cars_tags.tag_id = '9031cec30-df27-471e-858d-53c3d9657c8a')
ORDER BY "cars"."review"."score" DESC LIMIT 100
The query simply finds all reviews where there exists a cars_tags entry for the two tag_id's you're after.

postgresql count distinct on differect condition

I'm stuck on an exercise where I need to count the total amount of unique visits to planets, but if the planet is the moon (maan), then it should be counted twice. Also the client number should be 121
select case
when objectnaam = 'Maan' then count(objectnaam)
else count(distinct objectnaam)
end as aantal_bezoeken
from klanten inner join deelnames on klanten.klantnr = deelnames.klantnr
inner join reizen on deelnames.reisnr = reizen.reisnr
inner join bezoeken on reizen.reisnr = bezoeken.reisnr
where klanten.klantnr = 121
group by objectnaam
And it gives me this result
aantal_bezoeken
1
4
1
1
but the result should be
aantal_bezoeken
7
I just need to add all these values together but I don't know how to,
or maybe there's a better more simple solution. It should be without subqueries
Try this:
select sum(aantal_bezoeken) as aantal_bezoeken from
(select case
when objectnaam = 'Maan' then count(objectnaam)
else count(distinct objectnaam)
end as aantal_bezoeken
from klanten inner join deelnames on klanten.klantnr = deelnames.klantnr
inner join reizen on deelnames.reisnr = reizen.reisnr
inner join bezoeken on reizen.reisnr = bezoeken.reisnr
where klanten.klantnr = 121
group by objectnaam) as a

How to Sum a result quantity in sql server with multiple records which several joins, does it need some subquery to do it?

I am wanting to get the SUM records of a query that I am writing
I have done simple SUM aggregates in the past, but I'm a bit rusty and wonder the best approach to getting the proper results.
Example of table with Quantity (imaps_inv)
ste_id ste_acct_id stk_id qty
1 1 001 5
1 2 001 10
1 3 001 15
So the query should NOT return 3 records, but only 1 record and so the query results SHOULD be
Site ID Stocking ID Qty
1 001 30
So you can see what I want to return
inv.qty is the Quantity field I wish to SUM , and the query I wrote up based on the tables is below.
SELECT ste.ste_id, ty.ste_ty_id, inv.qty
FROM dbo.imaps_inv inv WITH(NOLOCK)
INNER JOIN dbo.imaps_ste ste WITH(NOLOCK)
ON inv.ste_id = ste.ste_id
INNER JOIN dbo.imaps_ste_ty ty
ON ty.ste_ty_id = ste.ste_ty_id
INNER JOIN dbo.imaps_stk_acct acct WITH(NOLOCK)
ON acct.ste_id = ste.ste_id
INNER JOIN dbo.imaps_stk_acct_ty aty WITH(NOLOCK)
ON aty.stk_acct_ty_id = acct.stk_acct_ty_id
WHERE
ste.inact_ind = 0
AND LTRIM(RTRIM(aty.stk_acct_ty_nm)) = 'Good'
AND acct.rsv_ind = 0
AND acct.inact_ind = 0
PLEASE LET ME KNOW WHAT I CAN PROVIDE TO MAKE IT MORE HELPFUL ( screenshots, schema etc... )
UPDATE,
well I was only getting 19 records and this co-worker said "oh, no.. you should be getting 16,000 records...
I said ok, i'm using this ste_id (site id) and when I sent him this query
SELECT distinct ste_id from [dbo].[imaps_inv] ( 20 records)
He said, to add in stk_id (stock #)
SELECT distinct ste_id, stk_id from [dbo].[imaps_inv] (15,910 records)
Therefore I updated my query to which I finally have the proper results and figured I would update my question with the combination of the persons answer along with me tweaking the code as other person certainly does not have the schema and records etc..
Final working query
SELECT ste.ste_id as 'Site ID', inv.stk_id as 'Stocking ID', SUM(inv.qty) Qty
FROM dbo.imaps_inv inv WITH(NOLOCK)
INNER JOIN dbo.imaps_ste ste WITH(NOLOCK)
ON inv.ste_id = ste.ste_id
INNER JOIN dbo.imaps_ste_ty ty
ON ty.ste_ty_id = ste.ste_ty_id
INNER JOIN dbo.imaps_stk_acct acct WITH(NOLOCK)
ON acct.ste_id = ste.ste_id
INNER JOIN dbo.imaps_stk_acct_ty aty WITH(NOLOCK)
ON aty.stk_acct_ty_id = acct.stk_acct_ty_id
WHERE
ste.inact_ind = 0
AND LTRIM(RTRIM(aty.stk_acct_ty_nm)) = 'Good'
AND acct.rsv_ind = 0
AND acct.inact_ind = 0
GROUP BY ste.ste_id, inv.stk_id
Use SUM:
SELECT ste.ste_id,
SUM(inv.qty) Qty
FROM dbo.imaps_inv inv WITH(NOLOCK)
INNER JOIN dbo.imaps_ste ste WITH(NOLOCK)
ON inv.ste_id = ste.ste_id
INNER JOIN dbo.imaps_ste_ty ty
ON ty.ste_ty_id = ste.ste_ty_id
INNER JOIN dbo.imaps_stk_acct acct WITH(NOLOCK)
ON acct.ste_id = ste.ste_id
INNER JOIN dbo.imaps_stk_acct_ty aty WITH(NOLOCK)
ON aty.stk_acct_ty_id = acct.stk_acct_ty_id
WHERE
ste.inact_ind = 0
AND LTRIM(RTRIM(aty.stk_acct_ty_nm)) = 'Good'
AND acct.rsv_ind = 0
AND acct.inact_ind = 0
GROUP BY ste.ste_id;