If Statements in where clause? - sql

So I have to run a query against a database schema: http://sqlfiddle.com/#!9/d0b643 , but an example schema would look like:
Table 1
itemID sale date salesmanID storeID
---------------------------------------------------
1 1/2015 1 1
1 3/2016 1 1
2 5/2016 2 1
2 1/2015 4 1
Table 2
itemID colorID price
--------------------------------------
1 1 23
1 2 10
1 3 13
2 1 11
2 2 14
2 3 18
Table 3
ColorID color
---------------------------------------
1 Red
2 Blue
3 Green
Table 4
SaleBegin SaleEnd ColorID salesmanID storeID
----------------------------------------------------------------
1/1/2014 12/31/2014 1 0 1
1/1/2015 12/31/2015 2 0 1
1/1/2016 12/31/2016 3 0 1
1/1/2014 12/31/2014 3 2 1
1/1/2015 12/31/2016 2 2 1
I need to have something in the where clause that pretty much says if there is a SalesmanID and the saleDate from Table1 falls between the StartDate and Enddate of Table4, use that color. Otherwise, if there is no salesmanID, use the StoreID (in this example they are all 1, but they could be different).
The current query I am adding this to is:
select t1.itemID,t3.color,t2.price
from table_1 t1
LEFT JOIN table_2 t2
ON t1.itemID = t2.itemID
LEFT JOIN table_3 t3
ON t2.colorID = t3.colorID
LEFT JOIN table_4 t4
ON t3.colorID = t4.colorID
WHERE t1.sale_date BETWEEN saleBegin and saleEnd;
How can I run this? The expected results should look like:
itemID color price
1 Blue 10
1 Green 13
2 Blue 14
2 Blue 14

I am trying to use MSSQL logic. and try it in SQL fiddle it run success.
Just try this code yourself to see if this is what you want.
select t1.itemID,t3.color,t2.price from table_1 t1
LEFT JOIN table_4 t41
on t1.sale_date BETWEEN t41.saleBegin and t41.saleEnd
and t41.salesmanID!=0 and t1.salesmanID=t41.salesmanID
LEFT JOIN table_4 t42
on t1.sale_date BETWEEN t42.saleBegin and t42.saleEnd
and t42.salesmanID=0 and t1.storeID=t42.storeID
INNER JOIN table_2 t2
ON t1.itemID = t2.itemID
INNER JOIN table_3 t3
ON t2.colorID = t3.colorID and t2.colorID=IF(ISNULL(t41.colorID),t42.colorID,t41.colorID)
order by t1.itemID,t3.color,t2.price;

I think this is what you want. You will get too many rows because of overlaps between store # and Sale dates. Once I changed your sample data table4 to have the last two rows be store #2 I get the results you posted.
1/1/2014 12/31/2014 3 2 2
1/1/2015 12/31/2016 2 2 2
Select t1.itemID,t3.color,t2.price
From table_1 t1
LEFT JOIN table_4 t4 ON t1.sale_date BETWEEN t4.saleBegin And t4.saleEnd And t1.SalesmanID = t4.SalesmanID
LEFT JOIN table_4 t4a ON t1.sale_date BETWEEN t4a.saleBegin And t4a.saleEnd And t1.StoreID = t4a.StoreID
LEFT JOIN table_2 t2 ON t1.itemID = t2.itemID And t2.ColorID = t4a.ColorID
LEFT JOIN table_3 t3 ON t2.colorID = t3.colorID
Where t4.SalesmanID Is Null
Group By t1.itemID,t3.color,t2.price
Union All
Select t1.itemID,t3.color,t2.price
From table_1 t1
LEFT JOIN table_4 t4 ON t1.sale_date BETWEEN t4.saleBegin And t4.saleEnd And t1.SalesmanID = t4.SalesmanID
LEFT JOIN table_2 t2 ON t1.itemID = t2.itemID And t2.ColorID = t4.ColorID
LEFT JOIN table_3 t3 ON t2.colorID = t3.colorID
Where t4.SalesmanID Is Not Null
itemID color price
1 Blue 10.000
1 Green 13.000
2 Blue 14.000
2 Blue 14.000

Related

SQL Server : select from multiple tables and calculate percentages

I have four tables and I would need to extract data from them to calculate the percentage
Table1
ID FK1 FK2
------------------
1 1 1
2 2 2
3 3 3
Table2
ID Name
------------------
1 L1
2 A1
3 B
Table3
ID FK3
------------------
1 1
2 2
3 3
Table4
ID Name
------------------
1 BA
2 N
3 CE
Now I need to get a Name from table4, which will be displayed as individual rows and then a Name from table2, which will be listed as individual columns and the value will then be a percentage of the record from table4:
Name L1 A1 B
---------------------------
BA 20(%) 40(%) 40(%)
N 30(%) 20(%) 30(%)
CE 15(%) 15(%) 70(%)
Because there are links, I'll give an example of what question I have now
select t3.Name
from table1 t1 (nolock)
join table2 t2 (nolock) on t1.FK1 = t2.ID
join table3 t3 (nolock) on t1.FK2 = t3.ID
join table4 t4 (nolock) on t2.FK3 = t4.ID
Does anyone have any idea how to do this? Thank you very much

Join two tables, using value from the first unless it is null, otherwise use value from the second

I have three tables which look like those:
TABLE 1
id j_id
1 1
2 2
3 3
TABLE 2
id j_id table1_id
1 57 1
2 84 1
3 1 1
4 9 2
5 2 2
and every j has a value in a third table
id value
1 1abc
2 2bcd
3 3abc
57 57abc
84 84abc
9 9abc
I am trying to write a query which will join table 1 and table 2 and use the J value from the third table instead of the j_id, but the problem is that I want to use the j value from the second table if it exists and otherwise use the value from the first table.
in order the make it clearer this is my query result without using the third table:
tbl1.j_id tbl2.j_id
1 1
1 84
1 57
2 2
2 9
3 null
I want the end query result to use the second table's j value unless it is null:
tbl1.j_id tbl2.j_id j_id
1 1 1abc
1 84 84abc
1 57 57abc
2 2 2abc
2 9 9abc
3 null 3abc
(Question and title edits are more than welcome, weren't that sure how to phrase them..)
You can simply JOIN to table3 on the COALESCE of table2.j_id and table1.j_id:
SELECT t1.j_id AS t1_j_id, t2.j_id AS t2_j_id, t3.value
FROM table1 t1
LEFT JOIN table2 t2 ON t2.table1_id = t1.id
JOIN table3 t3 ON t3.id = COALESCE(t2.j_id, t1.j_id)
Output:
t1_j_id t2_j_id value
1 1 1abc
1 57 57abc
1 84 84abc
2 2 2bcd
2 9 9abc
3 null 3abc
Demo on dbfiddle
One solution is to left join table3 twice:
select
t1.j_id,
t2.j_id,
coalesce(t31.value, t32.value) j_value
from
table1 t1
left join table2 t2 on t2.table1_id = t1.id
left join table3 t31 on t31.id = t2.j_id
left join table3 t32 on t32.id = t1.j_id

How to get Oracle to return unique results in a one to many relationship tables with a left join

I have a three tables
Table 1
Id Department
1 A
2 B
3 C
4 D
Table 2
Id DepartId Name
1 1 ABC
2 1 DEF
3 1 ASD
4 2 FGH
5 2 HJK
6 3 ZXC
Table 3
Id Depart Area
1 A pp
2 B
3 C nn
4 D oo
I need the result
Id Depart Name Area
1 A ABC pp
2 B FGH Null
3 C ZXC nn
4 D NULL oo
I need one matching entry from table 2 and table 3 to corresponding entry in the table 1
Do a left join to also get t1 rows without any reference in the t2 table. GROUP BY to get only 1 row per Department.
select t1.id, t1.Department, min(t2.Name)
from t1
left join t2 on t1.id = t2.DepartId
group by t1.id, t1.Department
I think I would do this with a correlated subquery:
select t1.*,
(select t2.name
from t2
where t1.id = t2.DepartId and rownum = 1
) as t2name
from t1;
This saves the overhead of an aggregation. An index on t2(DepartId, name) is optimal for this query.
by the way not the answer to your specific question but if instead of just one you want all the names you can use listagg
SELECT t1.id,
department,
LISTAGG (name, ',') WITHIN GROUP (ORDER BY name) names
FROM t1, t2
WHERE t1.id = t2.departId(+)
GROUP BY t1.id, department
ORDER BY 1
ID Department Names
1 A ABC,ASD,DEF
2 B FGH, HJK
3 C ZXC
4 D

SQL nested Inner Joins? Or Where Clause On Inner Joins?

I am having an issue with a query I am trying to write. Unfortunately I can only query against the database and cannot change the schema. Here are some simplified example tables:
Table 1
itemID sale date
----------------------------
1 1/2015
1 3/2016
2 5/2016
2 1/2015
Table 2
itemID colorID price
--------------------------------------
1 1 23
1 2 10
1 3 13
2 1 11
2 2 14
2 3 18
Table 3
ColorID color
---------------------------------------
1 Red
2 Blue
3 Green
Table 4
SaleBegin SaleEnd ColorID
----------------------------------------
1/1/2014 12/31/2014 1
1/1/2015 12/31/2015 2
1/1/2016 12/31/2016 3
Now I need a query that essentially gets the price and color for both item ids in the first table. I'm not sure how to do it with this schema even just for one. I tried something like:
SELECT item_id, price, color FROM Table1 T1
INNER JOIN Table2 T2
ON T1.ItemID=T2.ItemID
INNER JOIN Table3 T3
ON T2.ColorID=T3.ColorID
INNER JOIN Table4 T4
ON T3.ColorID=T4.ColorID
WHERE T1.itemID between SaleBegin AND SaleEnd
But it's not working for me, instead giving me every possible color and price for each item. What am I doing wrong? How do I get those values? Expected results should look like:
itemID color price
------------------------------------
1 Blue 10
1 Green 13
2 Green 18
2 Blue 14
http://sqlfiddle.com/#!9/e6fac/4
SELECT t1.itemID
, t3.color
, t2.price
FROM table_1 t1
LEFT JOIN table_2 t2
ON t1.itemID = t2.itemID
LEFT JOIN table_3 t3
ON t2.colorID = t3.colorID
LEFT JOIN table_4 t4
ON t3.colorID = t4.colorID
WHERE t1.sale_date BETWEEN saleBegin and saleEnd;
I'm not sure this is what you're looking for, but this query will give you the itemID, color and price for each product during each sale
SELECT
t4.SaleBegin
,t4.SaleEnd
,t1.itemID
,t3.color
,t2.price
FROM Table4 t4
INNER JOIN Table1 t1
ON t4.SaleBegin = CAST(REPLACE(t1.[sale date], '/', '/1/') AS DATE)
INNER JOIN Table2 t2
ON t1.itemID = t2.itemID
AND t4.ColorID = t2.ColorID
INNER JOIN Table3 t3
ON t4.ColorID = t3.colorID
Here is the SQL Fiddle

How to get the top row in join which is ordered by another column

I have an inner join on 2 tables.
Consider
Table1
sid name
1 abc
2 xyz
Table2
sdid sid detailname
1 1 a
2 1 b
3 2 x
So my query looks like below
SELECT *
FROM table1 t1
INNER JOIN table2 t2
ON t1.sid=t2.sid
the result i get is
sid name sdid sid detailname
1 abc 1 1 a
1 abc 2 1 b
2 xyz 3 2 x
I want to modify this query to get the highest 'sdid' from table 2
my end result should look like
sid name sdid sid detailname
1 abc 2 1 b
2 xyz 3 2 x
Include one more subquery in the join to get the max sdid for each sid from table2.
SELECT t1.sid,t1.name,t2.sdid,t2.sid,t2.detailname
FROM table1 t1
INNER JOIN table2 t2 ON t1.sid=t2.sid
INNER JOIN (select max(sdid) as maxsdid, sid from table2 group by sid) t21
ON t21.sid=t2.sid and t21.sdid = t2.sdid