SQL Query : Facing issues to get desired records from different tables - sql

I have two tables
Calendar (Calname, CCode, PCode)
Lookup (LCode, Name)
Calendar table contains records like,
Calname | CCode | PCode
abc | O_R | P_R
xyz | C_R | P_C
Lookup table contains records like,
LCode | Name
O_R | Reporting
C_R | Cross
P_R | Process
P_C | ProcessCross
I have to fetch the records in a way where I can get the name of all codes from lookup table which contains the record rowwise.
Desired Output,
Calname | CCode | PCode | CCodeName | PCodeName
abc | O_R | P_R | Reporting | Process
xyz | C_R | P_C | Cross | ProcessCross
I can not apply simply inner join on the basis of code it will not give me desired output.
I tried to use subquery also but it not worked out somehow,
.
Can anyone help me out with this issue.
Thanks

You can try joining the Calendar table to the Lookup table twice, using each of the two codes.
SELECT
c.Calname,
c.CCode,
c.PCode,
COALESCE(t1.Name, 'NA') AS CCodeName,
COALESCE(t2.Name, 'NA') AS PCodeName
FROM Calendar c
LEFT JOIN Lookup t1
ON c.CCode = t1.LCode
LEFT JOIN Lookup t2
ON c.PCode = t2.LCode

An alternative to Tim's answer would be to use scalar subqueries, which may or may not give you some performance benefit due to scalar subquery caching:
SELECT
c.Calname,
c.CCode,
c.PCode,
COALESCE((SELECT l1.name FROM lookup l1 WHERE c.ccode = l1.lcode), 'NA') AS CCodeName,
COALESCE((SELECT l2.name FROM lookup l2 WHERE c.pcode = l2.lcode), 'NA') AS PCodeName
FROM Calendar c;
I would test both answers to see which one works best for your data.

Related

SQL Server avoid repeat same joins

I´m doing the query below where I´m repeating the same joins multiple times, there is a better way to do it? (SQL Server Azure)
Ex.
Table: [Customer]
[Id_Customer] | [CustomerName]
1 | Tomy
...
Table: [Store]
[Id_Store] | [StoreName]
1 | SuperMarket
2 | BestPrice
...
Table: [SalesFrutes]
[Id_SalesFrutes] | [FruteName] | [Fk_Id_Customer] | [Fk_Id_Store]
1 | Orange | 1 | 1
...
Table: [SalesVegetable]
[Id_SalesVegetable] | [VegetableName] | [Fk_Id_Customer] | [Fk_Id_Store]
1 | Pea | 1 | 2
...
Select * From [Customer] as C
left join [SalesFrutes] as SF on SF.[Fk_Id_Customer] = C.[Id_Customer]
left join [SalesVegetable] as SV on SV.[Fk_Id_Customer] = C.[Id_Customer]
left join [Store] as S1 on S1.[Id_Store] = SF.[Fk_Id_Store]
left join [Store] as S2 on S1.[Id_Store] = SV.[Fk_Id_Store]
In my real case, I have many [Sales...] to Join with [Customer] and many other tables similar to [Store] to join to each [Sales...]. So it starts to scale a lot the number on joins repeating. There is a better way to do it?
Bonus question: I do like also to have FruteName, VegetableName, StoreName, and each Food table name under the same column.
The Expected Result is:
[CustomerName] | [FoodName] | [SalesTableName] | [StoreName]
Tomy | Orange | SalesFrute | SuperMarket
Tomy | Pea | SalesVegetable | BestPrice
...
Thank you!!
So based on the information provided, I would have suggested the below, to use a cte to "fix" the data model and make writing your query easier.
Since you say your real-world scenario is different to the info provided it might not work for you, but could still be applicable if you have say 80% shared columns, you can just use placeholder/null values where relevant for unioning the data sets and still minimise the number of joins eg to your store table.
with allSales as (
select Id_SalesFrutes as Id, FruitName as FoodName, 'Fruit' as SaleType, Fk_Id_customer as Id_customer, Fk_Id_Store as Id_Store
from SalesFruits
union all
select Id_SalesVegetable, VegetableName, 'Vegetable', Fk_Id_customer, Fk_Id_Store
from SalesVegetable
union all... etc
)
select c.CustomerName, s.FoodName, s.SaleType, st.StoreName
from Customer c
join allSales s on s.Id_customer=c.Id_customer
join Store st on st.Id_Store=s.Id_Store

Table Left Join

I'm currently trying to get an output from two tables that I want to join and it seems like I have a block in my mind on how to resolve this.
Table 1 has products with unique IDs.
ID | (other info)
-----------------
AA |
BB |
CC |
Table 2 has the unique ID of Table 1 as FK as well as a model number and a part-code that I would like to join onto Table 1. Table 2 has a multitude of other information resulting in the following possible constellation:
ID | FK | model number | part-code
-----------------------------------
01 | AA | model0001 | part923
02 | AA | model0001 |
03 | AA | | part923
04 | BB | model0002 |
05 | BB | | part876
06 | CC | | part551
Information in Table 2 is therefore very scattered and not necessarily complete. I also do not want to assume that for a given FK the model number and the part-code remain the same across all entries (if there are multiple variants for a given FK, I only want one entry, even if it is at random).
The result I am trying to achieve is to get all the information I extract from Table 1, and it is given that there will always be a unique ID (=FK in Table 2), and add the model number and part-code, if existing, to the table without creating any duplicates. The example above should therefore give the following output.
ID | model number | part-code | (other info from table 1)
---------------------------------------------------------
AA | model0001 | part923 |
BB | model0002 | part876 |
CC | | part551 |
I should also mention that Table 2 is extremely large (millions of entries) and I have no way to match the data except with the IDs from Table 1. This table is also quite big - an efficient way of approaching this is therefore necessary.
Thank you for your time in reading this and helping me understand how to approach this.
Best,
Jonas
You are right, you need an OUTER JOIN to get all the records in table1 with whatever matching records are in table2.
Getting only one record per hit from table2 is tricky. This aggregating subquery will produce your desired output. Note that this solution can produce a permutation of (model_number,part_code) which does not exist in any single record in table2 ; I guess it's okay as that is what your sample result set shows for BB. The performance across "millions of entries" may be slow. But that is a (separate) tuning issue.
select t1.id
, t2.model_number
, t2.part_code
, t1.whatever
, t1.blah
, t1.etc
from table1 t1
left outer join ( select fk
, max (model_number) as model_number
, max (part_code) as part_code
from table2
group by fk ) t2
on t1.id = t2.fk
order by t1.id
/
You can try this SQL
SELECT t1.ID, t2.model_number, t2.part-code FROM table1 t1
LEFT JOIN table2 t2 ON t1.ID = t2.FK
GROUP BY t1.ID
Hope that helps!

Using self join on a table to compare two columns based on a linked column in the same table

I have the following:
TableA
ID | DocumentType | DocumentCode | DocumentDate | Warehouse | RefecenceCode
---+--------------+--------------+--------------+-----------+--------------
1 | DeliveryNote | DOC-001 | 2017-04-21 | 1 | NULL
2 | Invoice | DOC-002 | 2017-04-21 | 2 | DOC-001
As you can see, the warehouse is different on each document and DOC-002 is related to DOC-001 through the information in ReferenceCode column (which means that was created starting from DOC-001 as a source document).
It is supposed for the DOC-002 to have the same information but sometimes might be different and in this case, I was tried to create a query (I think self join applies here) in order to check what information is different in the DOC-002 in this case compared to DOC-001, based on the reference code, but I couldn't managed to do it.
If someone could give me a hand, I'll be very grateful.
This is the SQL query:
select *
from TableA tbl
inner join TableA tbla on tbl.id = tbla.id
where tbla.ReferenceCode = tbl.DocumentCode
You indeed want to join the table to itself. But joining on the ID column won't work, because that column doesn't relate records to each other. Instead, you need to join on the DocumentCode and ReferenceCode fields. Then only include the records that have some difference (in this case, I'm only comparing the DocumentDate and Warehouse fields).
select tbla.*
from TableA tbl
join TableA tbla on tbl.DocumentCode = tbla.ReferenceCode
where tbla.DocumentDate != tbl.DocumentDate
or tbla.Warehouse != tbl.Warehouse

combine 2 sql's from different tables into one query

I have for example as first query: (ararnr = article number)
Select ararnr,ararir,aoarom from ar left join ao ON AR.ARARNR=AO.AOARNR WHERE AR.ARARKD=1389
the second query uses the result from the first column from the first query to search in another table
Select votgan, sum(ststan) as totalStock from vo INNER JOIN st on vo.voarnr=st.starnr where voarnr = ararnr
How could I combine both ?
Please note : Not all articlenumbers from the first query will be found in the second, but I need them in my result.
In the result I need the columns from both queries.
EDIT
for example :
first query returns article numbers and the description:
+---------+--------------+
| ararnr | aoarom |
+---------+--------------+
| a123456 | description1 |
| b123456 | description2 |
| 0123456 | description3 |
+---------+--------------+
second query returns the totalstock for those articles:
+---------+--------------+
| ararnr | totalstock |
+---------+--------------+
| a123456 | 12 |
| b123456 | |
| 0123456 | 6 |
+---------+--------------+
Note the second one doesn't return a value since the articlenumber doesn't exist in this table.
In my result I would like to get the articlenumber with corresponding description and stock.
+---------+--------------+-----------+---------+
| ararnr | aoarom | totalStock| vovoan |
+---------+--------------+-----------+---------+
| a123456 | description1 | 12 | 2 |
| b123456 | description2 | | 1 |
| 0123456 | description3 | 6 | |
+---------+--------------+-----------+---------+
I'm using sql on db2
SECOND EDIT
The first query will select some article numbers (ararnr) from table ar and find the corresponding description (aoarom) in another table ao.
The second query finds the stock (vovoan and sum ststan) from two differend tables vo and st for the article numbers found in the first query.
The result should have the article number with corresponding description with corresponding stock from vo and st
I can't fully understand what you're asking, but another join may assist you.
example:
SELECT ar.ararnr, ar.ararir, ar.ararom, vo.votgan, SUM(vo.ststan) as totalStock
FROM ar LEFT JOIN ao ON [id=id] LEFT JOIN vo ON [id=id]
Because I can't tell what your tables structure are, or what you're really asking for, this is the best response I can give you.
This also may be what you're looking for:
Combining 2 SQL queries and getting result set in one
You can use this query.
SELECT ar.ararnr, ar.ararir, ar.ararom, vo.votgan, SUM(vo.ststan) as totalStock
FROM ar
LEFT JOIN ao ON ao.ararnr = ar.ararnr
LEFT JOIN vo ON vo.voarnr = ao.ararnr
If you are using SQL Server as database then this can be done with help of OUTER APPLY
SELECT ararnr,aoarom ,temp.totalStock
FROM ar
LEFT JOIN ao ON AR.ARARNR=AO.AOARNR
OUTER APPLY(
SELECT sum(ststan) as totalStock
FROM vo
INNER JOIN st on vo.voarnr=st.starnr
where voarnr = ar.ararnr
)temp
WHERE AR.ARARKD=1389
You'd get a much more complete answer if you were to post the table structure and desired result, but..
You can use the first query as a resultset for your second query, and join to it. something like:
Select
votgan,
sum(ststan) as totalStock
from vo
inner join (Select
ararnr,
ararir,
ararom
from ar
left join ao .....) z on vo.voarnr = z.ararnr
EDIT:
Select
votgan,
sum(ststan) as totalStock,
z.ararnr,
z.aoarom
from vo
inner join (Select
ararnr,
ararir,
ararom
from ar
left join ao .....) z on vo.voarnr = z.ararnr

INNER JOIN Need to use column value twice in results

I've put in the requisite 2+ hours of digging and not getting an answer.
I'd like to merge 3 SQL tables, where Table A and B share a column in common, and Table B and C share a column in common--Tables A and C do not.
For example:
Table A - entity_list
entity_id | entity_name | Other, irrelevant columns
Example:
1 | Microsoft |
2 | Google |
Table B - transaction_history
transaction_id | purchasing_entity | supplying_entity | other, irrelevant columns
Example:
1 | 2 | 1
Table C - transaction_details
transactional_id | amount_of_purchase | Other, irrelevant columns
1 | 5000000 |
Using INNER JOIN, I've been able to get a result where I can link entity_name to either purchasing_entity or supplying_entity. And then, in the results, rather than seeing the entity_id, I get the entity name. But I want to substitute the entity name for both purchasing and supplying entity.
My ideal results would look like this:
1 [transaction ID] | Microsoft | Google | 5000000
The closes I've come is:
1 [transaction ID] | Microsoft | 2 [Supplying Entity] | 5000000
To get there, I've done:
SELECT transaction_history.transaction_id,
entity_list.entity_name,
transaction_history.supplying_entity,
transaction_details.amount_of_purchase
FROM transaction.history
INNER JOIN entity_list
ON transaction_history.purchasing_entity=entity_list.entity.id
INNER JOIN
ON transaction_history.transaction_id=transaction_details.transaction_id
I can't get entity_name to feed to both purchasing_entity and supplying_entity.
Here is the query:
SELECT h.transaction_id, h.purchasing_entity, purchaser.entity_name, h.supplying_entity, supplier.entity_name, d.amount_of_purchase
FROM transaction_history h
INNER JOIN transaction_details d
ON h.transaction_id = d.transaction_id
INNER JOIN entity_list purchaser
ON h.purchasing_entity = purchaser.entity_id
INNER JOIN entity_list supplier
ON h.supplying_entity = supplier.entity_id