Trouble with adding additional column with JOIN - sql

Have two tables:
Task:
Make a table with fields:
name of acquiring_company;
name of acquired_company;
price_amount;
funding_total;
Ignore those transactions in which the purchase amount (price_amount) and amount of investment (funding_total) is zero
SELECT
a.acquiring_company_id,
a.acquired_company_id,
a.price_amount,
c.funding_total
FROM acquisition a
LEFT JOIN company c
ON a.acquired_company_id = c.id
WHERE price_amount <> 0 AND funding_total <> 0
Maybe a dumb question, but how can I add names to acquiring_company and acquired_company (company.name)? I don't understand it because there are two id fields. I can't use JOIN on both of them.

Join the same table twice with different alias names
SELECT a.acquired_company_id, c1.name as acquired_company_name,
a.acquiring_company_id, c2.name as acquiring_company_name,
a.price_amount,
c1.funding_total
FROM acquisition a
LEFT JOIN company c1 ON a.acquired_company_id = c1.id
LEFT JOIN company c2 ON a.acquiring_company_id = c2.id
WHERE a.price_amount <> 0
AND c1.funding_total <> 0

I can't use JOIN on both of them.
Yes, you can. And should.
SELECT
a.acquiring_company_id,
a.acquired_company_id,
a.price_amount,
c1.funding_total,
c1.name as acquired_company_name,
c2.name as acquiring_company_name
FROM acquisition a
LEFT JOIN company c1
ON a.acquired_company_id = c1.id
LEFT JOIN company c2
ON a.acquiring_company_id = c2.id
WHERE price_amount <> 0 AND c1.funding_total <> 0
Test the query in Db<>fiddle.

Related

How to subtract from another table in SQL

SELECT
COUNT(ca.Plate) as 'OccupiedElectricSlots'
FROM cities C
JOIN ParkingHouses HS on C.Id = hs.CityId
JOIN ParkingSlots PS on HS.Id = ps.ParkingHouseId
LEFT JOIN Cars Ca on PS.Id = Ca.ParkingSlotsId
WHERE ps.ElectricOutlet = 1
GROUP BY hs.HouseName, C.CityName
SELECT
MAX(Ps.SlotNumber) as 'ParkingSlotTotal'
,MAX(PS.SlotNumber) - Count(ca.Plate) as 'FreeSlots'
,SUM(CAST(PS.ElectricOutlet AS INT)) as 'ElectricOutlet'
,Hs.HouseName
,C.CityName
FROM Cities C
JOIN ParkingHouses HS on C.Id = hs.CityId
JOIN ParkingSlots PS on HS.Id = ps.ParkingHouseId
LEFT JOIN Cars Ca on PS.Id = Ca.ParkingSlotsId
GROUP BY hs.HouseName, C.CityName
How can I subtract the first tables numbers on the second one?
I want to see how many free slots that have electric outlet.
Like this Column ElectricOutlet - OccupiedElectricSlots = result
I'm quite new at SQL, but I have tried to outer apply (don't fully understand it), and I tried to join them both tables togheter. Tried different where conditions but I'm stuck atm.
Your queries are almost identical as far as I can see. You can change your first query to:
SELECT COUNT(CASE WHEN ps.ElectricOutlet = 1 THEN ca.Plate END) as 'OccupiedElectricSlots'
FROM cities C
JOIN ParkingHouses HS on C.Id = hs.CityId
JOIN ParkingSlots PS on HS.Id = ps.ParkingHouseId
LEFT JOIN Cars Ca on PS.Id = Ca.ParkingSlotsId
GROUP BY hs.HouseName, C.CityName
I.e., instead of filtering on ps.ElectricOutlet you just ignore those rows in COUNT. Now you can just:
SELECT
[...]
,SUM(CAST(PS.ElectricOutlet AS INT)) - COUNT(CASE WHEN ...) AS result
[...]
FROM Cities C
JOIN ParkingHouses HS
ON C.Id = hs.CityId
JOIN ParkingSlots PS
ON HS.Id = ps.ParkingHouseId
LEFT JOIN Cars Ca
ON PS.Id = Ca.ParkingSlotsId
GROUP BY hs.HouseName, C.CityName
The MINUS operator is used to subtract the result set obtained by first SELECT query from the result set obtained by second SELECT query.
MINUS compares the data in two tables and returns only the rows of data using the specified columns that exist in the first table but not the second.

Comparing values in two rows and getting ORA-00918: column ambiguously defined

I am trying to compare values from one column in two different rows using CASE statement. Inner SELECT statements are identical and working OK giving me fields that I need. Then I inner joined them on one of the key fields (KYCID). That's where I get "column ambiguously defined" error. I tried to remove duplicate rows by using DISTINCT - still the same error.
SELECT DISTINCT e.KYCID,
CASE WHEN e.HRAC_FLAG <> f.HRAC_FLAG THEN 'FALSE' ELSE 'TRUE' END AS FLAG_COMPARISON
FROM
(SELECT gt.task_id, gt.work_item_status, gt.work_item_type, gt.component_id, xref.HRAC_FLAG,
xref.case_nbr, xref.task_id, d.kycid, d.core_component_state
FROM kyc_gbl_main.global_task gt
inner join KYC_RGN_NAM_MAIN.CASE_HRAC_XREF xref on gt.component_id = xref.component_id
inner join kyc_rgn_nam_main.account a on xref.accountid = a.accountid
inner join kyc_rgn_nam_main.country_appx_account_xref b on a.accountid = b.accountid
inner join kyc_rgn_nam_main.country_appx c on c.cntry_appx_id = b.cntry_appx_id and
c.country_appx_state = b.country_appx_state
inner join kyc_rgn_nam_main.kyc_main d on d.kycid = c.kycid
where gt.work_item_type = 'HRAC_OVERLAY'
and gt.work_item_status = 'Completed') e
INNER JOIN
(select gt.task_id, gt.work_item_status, gt.work_item_type, gt.component_id, xref.HRAC_FLAG,
xref.case_nbr, xref.task_id, d.kycid, d.core_component_state
from kyc_gbl_main.global_task gt
inner join KYC_RGN_NAM_MAIN.CASE_HRAC_XREF xref on gt.component_id = xref.component_id
inner join kyc_rgn_nam_main.account a on xref.accountid = a.accountid
inner join kyc_rgn_nam_main.country_appx_account_xref b on a.accountid = b.accountid
inner join kyc_rgn_nam_main.country_appx c on c.cntry_appx_id = b.cntry_appx_id and
c.country_appx_state = b.country_appx_state
inner join kyc_rgn_nam_main.kyc_main d on d.kycid = c.kycid
where gt.work_item_type = 'HRAC_OVERLAY'
and gt.work_item_status = 'Completed') f
ON e.KYCID = f.KYCID
WHERE e.core_component_state ='ACTIVE'
AND f.core_component_state = 'IN_PROGRESS';
As determined with process of elimination, you reference the same named column in a SELECT query. To avoid this name collision, consider aliasing those particular columns.
Additionally, to avoid repetition, consider using a CTE via WITH and avoid using table aliases like (a, b, c) or (t1, t2, t3). Finally, move WHERE conditions to ON to filter before combining all data sources.
WITH sub AS (
SELECT gt.task_id AS gt_task_id -- RENAMED TO AVOID COLLISION
, gt.work_item_status
, gt.work_item_type
, gt.component_id
, xref.HRAC_FLAG
, xref.case_nbr
, xref.task_id AS x_ref_task_id -- RENAMED TO AVOID COLLISION
, k.kycid
, k.core_component_state
FROM kyc_gbl_main.global_task gt
INNER JOIN KYC_RGN_NAM_MAIN.CASE_HRAC_XREF xref
ON gt.component_id = xref.component_id
AND gt.work_item_type = 'HRAC_OVERLAY' -- MOVED FROM WHERE
AND gt.work_item_status = 'Completed' -- MOVED FROM WHERE
INNER JOIN kyc_rgn_nam_main.account acc
ON xref.accountid = acc.accountid
INNER JOIN kyc_rgn_nam_main.country_appx_account_xref cax
ON acc.accountid = cax.accountid
INNER JOIN kyc_rgn_nam_main.country_appx ca
ON ca.cntry_appx_id = cax.cntry_appx_id
AND ca.country_appx_state = cax.country_appx_state
INNER JOIN kyc_rgn_nam_main.kyc_main k
ON k.kycid = ca.kycid
)
SELECT DISTINCT
e.KYCID
, CASE
WHEN e.HRAC_FLAG <> f.HRAC_FLAG
THEN 'FALSE'
ELSE 'TRUE'
END AS FLAG_COMPARISON
FROM sub e
INNER JOIN sub f
ON e.KYCID = f.KYCID
AND e.core_component_state = 'ACTIVE' -- MOVED FROM WHERE
AND f.core_component_state = 'IN_PROGRESS' -- MOVED FROM WHERE

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.

Joining 4 tables in SQL

I have a question regarding joining 4 tables. This is my query.
SELECT
a.pick_id, a.Serial_No, a.Work_Ord_No, a.Lot_No,
a.Product_no, a.Plan_Qty, a.Machine_no, a.shift, a.Scan_dt,
b.Trml_code,
case when c.Wire_Type is null then '-' else c.Wire_Type +' '+ c.Wire_Size+' '+c.Wire_Color end as Wire,
case when d.Mtrl_code is null then '-' else d.Mtrl_code end as Material
FROM
pickMaster a
JOIN
pickTerminal b ON b.id = a.id
JOIN
pickWire c ON c.id = a.id
JOIN
pickInserting d ON d.id = a.id
This is the data for 4 table before I join them.
And this is the result after I join them.
The problem is after I join the 4 table the result show 4 row with the same data on material and wire. How to solve this?. Any idea?.
Because, You have double-IDs (103) for the last two tables.
You have a Cartesian product between pickTerminal and pickInserting.
You need to connect this two tables somehow.
Example!! This is the only attribute i see as common?!
SELECT
a.pick_id, a.Serial_No, a.Work_Ord_No, a.Lot_No,
a.Product_no, a.Plan_Qty, a.Machine_no, a.shift, a.Scan_dt,
b.Trml_code,
case when c.Wire_Type is null then '-' else c.Wire_Type +' '+ c.Wire_Size+' '+c.Wire_Color end as Wire,
case when d.Mtrl_code is null then '-' else d.Mtrl_code end as Material
FROM
pickMaster a
JOIN
pickTerminal b ON b.id = a.id
JOIN
pickWire c ON c.id = a.id
JOIN
pickInserting d ON d.id = a.id
and d.mtrl_side = b.Trml_side <-- add this
but without more context its hard to tell how you can archive this.
Since you don`t need any information from the 3rd or 4th tables except the distinct material/ terminal codes , you can use left join instead of join for the last two joins.

MS Access (via VB.NET) - convert linked attribute tables to columns in output

I've searched, and found a lot of similar things, but not quite what I'm looking for.
I have what are essentially a bunch of linked tables with attributes and values.
xxBio table
xxBio_ID xxBio_LINK
1 100
2 101
xx table
xxBio_LINK xxAttr_LINK
100 1000
101 2000
xxAttr table
xxAttr_LINK xxAttrCat_1_LINK xxAttrCat_2_LINK
1000 null 550
2000 650 null
xxAttrCat_1 table
xxAttrCat_1_LINK xxAttrCat_1_Description xxAttrCat_1_Value
650 wumpus 20
xxAttrCat_2 table
xxAttrCat_2_LINK xxAttrCat_2_Description xxAttrCat_2_Value
550 frith 30
OUTPUT NEEDS TO BE:
xxBio_ID frith wumpus
1 30 null
2 null 20
I can easily see how to get the result set with columns like attribute_name1, attribute_value1, attribute_name2, attribute_value2, and so forth.
SELECT xxBio.ID, xxAttrCat_1.xxAttrCat_1_Description, xxAttrCat_1.xxAttrCat_1_Value, xxAttrCat_2.xxAttrCat_2_Description, xxAttrCat_2.xxAttrCat_2_Value
FROM ((
(xx INNER JOIN xxBio ON xx.xxBio_LINK = xxBio.xxBio_LINK)
INNER JOIN xxAttr ON xx.xxAttr_LINK = xxAttr.xxAttr_LINK)
LEFT JOIN xxAttrCat_1 ON xxAttr.xxAttrCat_1_LINK = xxAttrCat_1.xxAttrCat_1_LINK)
LEFT JOIN xxAttrCat_2 ON xxAttr.xxAttrCat_2_LINK = xxAttrCat_2.xxAttrCat_2_LINK
But that's not what we need. We need the attribute names to be column names.
How do we achieve this?
Update to question:
It turned out that we misunderstood the requirements, so we had to take a different route and did not get to try the answers. I appreciate the help.
Put the SQL in a string and execute from VBA. (Dynamic SQL?)
sql = "SELECT xxBio.ID, " & xxAttrCat_1.xxAttrCat_1_Description & ", " & ...
Consider using IIF() conditional statements:
SELECT xxBio.ID,
IIF(xxAttrCat_1.xxAttrCat_1_Description = 'wumpus',
xxAttrCat_1.xxAttrCat_1_Value, NULL) As [wumpus],
IIF(xxAttrCat_2.xxAttrCat_2_Description = 'frith',
xxAttrCat_2.xxAttrCat_2_Value, NULL) As [frith]
FROM (((xx
INNER JOIN xxBio ON xx.xxBio_LINK = xxBio.xxBio_LINK)
INNER JOIN xxAttr ON xx.xxAttr_LINK = xxAttr.xxAttr_LINK)
LEFT JOIN xxAttrCat_1 ON xxAttr.xxAttrCat_1_LINK = xxAttrCat_1.xxAttrCat_1_LINK)
LEFT JOIN xxAttrCat_2 ON xxAttr.xxAttrCat_2_LINK = xxAttrCat_2.xxAttrCat_2_LINK
If each ID can have multiple values along same descriptions and you need to sum or average all corresponding values, then turn query into conditional aggregation (known as pivoting). Below also uses table aliases, a, b, c1, c2 for brevity and organization.
SELECT b.ID,
SUM(IIF(c1.xxAttrCat_1_Description='wumpus', c1.xxAttrCat_1_Value, NULL)) As [wumpus],
SUM(IIF(c2.xxAttrCat_2_Description='frith', c2.xxAttrCat_2_Value, NULL)) As [frith]
FROM (((xx
INNER JOIN xxBio b ON xx.xxBio_LINK = b.xxBio_LINK)
INNER JOIN xxAttr a ON xx.xxAttr_LINK = a.xxAttr_LINK)
LEFT JOIN xxAttrCat_1 c1 ON a.xxAttrCat_1_LINK = c1.xxAttrCat_1_LINK)
LEFT JOIN xxAttrCat_2 c2 ON a.xxAttrCat_2_LINK = c2.xxAttrCat_2_LINK
GROUP BY b.ID
And if such descriptions can be many use MS Access SQL's crosstab query. But since you have two categories, run a crosstab on each and save them as stored queries or views. Then, join together:
--CATEGORY 1
TRANSFORM SUM(c1.xxAttrCat_1_Value) AS SumOfValue
SELECT b.ID,
FROM ((xx
INNER JOIN xxBio b ON xx.xxBio_LINK = b.xxBio_LINK)
INNER JOIN xxAttr a ON xx.xxAttr_LINK = a.xxAttr_LINK)
LEFT JOIN xxAttrCat_1 c1 ON a.xxAttrCat_1_LINK = c1.xxAttrCat_1_LINK
GROUP BY b.ID
PIVOT c1.xxAttrCat_1_Description;
--CATEGORY 2
TRANSFORM SUM(c2.xxAttrCat_2_Value) AS SumOfValue
SELECT b.ID,
FROM ((xx
INNER JOIN xxBio b ON xx.xxBio_LINK = b.xxBio_LINK)
INNER JOIN xxAttr a ON xx.xxAttr_LINK = a.xxAttr_LINK)
LEFT JOIN xxAttrCat_2 c2 ON a.xxAttrCat_2_LINK = c2.xxAttrCat_2_LINK
GROUP BY b.ID
PIVOT c2.xxAttrCat_2_Description;
--CROSSTAB QUERIES JOIN
SELECT c1.*, c2.*
FROM Categ1CrossTabQ c1
INNER JOIN Categ1CrossTabQ c2
ON c1.ID = c2.ID;
Please note: comments above with double dash are not allowed in an Access query and only one statement is allowed in saved query. Access has a limit of 255 columns per table/query, so pivoted values greater than 255 will err out unless you use IN clause. Finally, you cannot use crosstabs as subqueries. And crosstabs are strictly an MS Access command and not used in other DBMS's.