convert subquery to use Cases and Join - oracle

I have a query which is working fine. I want to convert it to use Cases and Join.
SELECT id, Ticket_id, serial_no, operator,
(SELECT value FROM Forms_Details where FORM_ID = cv.id and status = 'ACTIVE' and key = 'COMPUTER_TYPE') as COMPUTER_TYPE,
(SELECT value FROM Forms_Details where FORM_ID = cv.id and status = 'ACTIVE' and key = 'BRAND') as BRAND,
(SELECT value FROM Forms_Details where FORM_ID = cv.id and status = 'ACTIVE' and key = 'MODEL') as MODEL,
status, datetime
FROM Form cv
where status = 'ACTIVE' order by id desc;

If you want to join, then join. What keeps you from doing so?
SELECT
f.id,
f.Ticket_id,
f.serial_no,
f.operator,
ct.value AS computer_type,
b.value AS brand,
m.value AS model,
f.status,
f.datetime
FROM form f
LEFT JOIN forms_details ct ON ct.form_id = f.id AND ct.status = 'ACTIVE' AND ct.key = 'COMPUTER_TYPE'
LEFT JOIN forms_detailswhere b ON b.form_id = f.id AND b.status = 'ACTIVE' AND b.key = 'BRAND'
LEFT JOIN forms_detailswhere m ON m.form_id = f.id AND m.status = 'ACTIVE' AND m.key = 'MODEL'
WHERE f.status = 'ACTIVE'
ORDER BY f.id DESC;
Or, in order not to read the same table twice, you can use conditional aggregation to get the values from the table:
SELECT
f.id,
f.Ticket_id,
f.serial_no,
f.operator,
ct.value AS computer_type,
fdw.brand,
fdw.model,
f.status,
f.datetime
FROM form f
LEFT JOIN forms_details ct ON ct.form_id = f.id AND ct.status = 'ACTIVE' AND ct.key = 'COMPUTER_TYPE'
LEFT JOIN
(
SELECT
form_id,
MAX(CASE WHEN key = 'BRAND' THEN value END) AS brand,
MAX(CASE WHEN key = 'MODEL' THEN value END) AS model
FROM forms_detailswhere
WHERE status = 'ACTIVE' AND key IN ('BRAND', 'MODEL')
GROUP BY form_id
) fdw ON fdw.form_id = f.id
WHERE f.status = 'ACTIVE'
ORDER BY f.id DESC;

You can PIVOT and then join:
SELECT cv.id,
cv.Ticket_id,
cv.serial_no,
cv.operator,
fd.computer_type,
fd.brand,
fd.model,
cv.status,
cv.datetime
FROM Form cv
LEFT OUTER JOIN (
SELECT *
FROM (
SELECT form_id, key, value
FROM Form_Details
WHERE status = 'ACTIVE'
)
PIVOT (
MAX(value)
FOR key IN (
'BRAND' AS brand,
'MODEL' AS model,
'COMPUTER_TYPE' AS computer_type
)
)
) fd
ON (cv.id = fd.form_id)
where cv.status = 'ACTIVE'
order by id desc;

Related

Oracle:if left join table return no rows then change to another left join table

I have two query as below and both of them work well. Now I need to combine them and if the first select find rows then no need to run the second select
1.
select f.*, o.org_sn, ttt.name linkman_name, ttt.phone phone_num
from td_archive_feedback f
left join TD_SM_ORG o
on f.recv_org_id = o.org_id
left join (--if this select returns no row , then change.if find matching rows then don't change
select wm_concat(linkman_name) name,
wm_concat(phone_num) phone,
org_id
from (select linkman_name, phone_num, LINK_ORG_ID, org_id
from TD_SM_LINKMAN
where STATE = '2'
and (LINK_ORG_ID = #link_org_id)) t
group by org_id) ttt
on ttt.org_id = o.org_id
--
left join td_sm_dict_item di
on o.org_level = di.item_id
where f.businessid = #businiessid
select f.*, o.org_sn, ttt.name linkman_name, ttt.phone phone_num
from td_archive_feedback f
left join TD_SM_ORG o
on f.recv_org_id = o.org_id
left join (--if the first left join return no rows ,then change to this
select wm_concat(linkman_name) name,
wm_concat(phone_num) phone,
t.org_id
from (
select linkman_name, phone_num, LINK_ORG_ID, org_id
from TD_SM_LINKMAN
where STATE = '2'
and (LINK_ORG_ID is null or LINK_ORG_ID = '')) t
group by t.org_id) ttt
on ttt.org_id = o.org_id
--
left join td_sm_dict_item di
on o.org_level = di.item_id
where f.businessid = #businessid;
Just like I remarked, if
select wm_concat(linkman_name) name,.... where STATE = '2'
and (LINK_ORG_ID = #link_org_id)) t
... returns no rows,
I want to change this to:
select wm_concat(linkman_name) name,.... where STATE = '2' and (LINK_ORG_ID is null or LINK_ORG_ID = '')) t.
Please help me, thanks.
Use Or condition:
select f.*, o.org_sn, ttt.name linkman_name, ttt.phone phone_num
from td_archive_feedback f
left join TD_SM_ORG o
on f.recv_org_id = o.org_id
left join (--if this select returns no row , then change
select wm_concat(linkman_name) name,
wm_concat(phone_num) phone,
org_id
from (select linkman_name, phone_num, LINK_ORG_ID, org_id
from TD_SM_LINKMAN
where STATE = '2'
and (
(LINK_ORG_ID = #link_org_id) or
(LINK_ORG_ID is null or LINK_ORG_ID = '')
) t
group by org_id) ttt
on ttt.org_id = o.org_id
--
left join td_sm_dict_item di
on o.org_level = di.item_id
where f.businessid = #businiessid

How do I convert this query into LINQ?

SELECT *
FROM
ProcedureLookup ProcLookup
INNER JOIN (SELECT PatientProcedures.PP_ProcedureId, COUNT(*) as ProcCount
FROM (PatientProcedures INNER JOIN Treatments ON PatientProcedures.PP_TreatmentId = Treatments.TS_TreatmentId)
WHERE YEAR(Treatments.TS_Date) = YEAR(GETDATE())
GROUP BY PatientProcedures.PP_ProcedureId) cyearProc ON ProcLookup.PL_ProcedureId = cyearProc.PP_ProcedureId
ORDER BY ProcCount DESC;
Here ProcedureLookup, Treatments, PatientProcedures are the tables.
Here linq query.
var result = (from ProcLookup in db.ProcedureLookup
join cyearProc in (
from p in db.PatientProcedures
join t in db.Treatments on p.PP_TreatmentId equals
t.TS_TreatmentId
where
t.TS_Date.Year == DateTime.Now.Year
group p by p.PP_ProcedureId into g
select new
{
PP_ProcedureId = g.Key,
ProcCount = g.Count()
}
) on ProcLookup.PL_ProcedureId equals
cyearProc.PP_ProcedureId
orderby cyearProc.ProcCount descending
select new
{
// Columns
PP_ProcedureId = ProcLookup.PP_ProcedureId,
ProcCount = cyearProc.ProcCount
}).ToList();

How do I "Order by" more than on column?

This is my query:
SELECT count(oi.id) imgCnt, o.*,
IF(pricet=2,c.currency_value*o.attributes_36*o.price,
c.currency_value*o.price) AS pprice, od.title, oi.image,
MIN(oi.id), ( c.currency_value * o.price ) AS fprice,
ag.agent_name, DATE_FORMAT( o.date_added, '%d-%m-%Y') as dadded
FROM i_offers_12 o
LEFT JOIN i_agents ag ON o.agents_id = ag.id
LEFT JOIN i_currencies c ON o.currencies_id = c.id
LEFT JOIN i_offers_details od ON ( o.id = od.offers_id AND od.languages_id = 1 )
LEFT JOIN i_offers_images oi ON ( oi.offers_id = o.id AND oi.o_id = '12' )
WHERE ( o.offer_status='active' OR o.offer_status='sold')
AND actions_id = '1'
AND c.id = o.currencies_id
AND o.counties_id = '2'
AND o.cities_id = '3'
GROUP BY o.id
ORDER BY dadded
DESC
I want to sort after dadded(which is of type date) and offer_status(which is of type enum).
I want to display first, all of the elements which have offer_status = 'active' and sort by dadded and after that all of the elements which have offer_status = 'sold' and sort also by dadded. How can I do that? thx
The fields you want to sort on MUST be part of the select statement:
SELECT count(oi.id) imgCnt, o.*,
IF(pricet=2,c.currency_value*o.attributes_36*o.price,
c.currency_value*o.price) AS pprice, od.title, oi.image,
MIN(oi.id), ( c.currency_value * o.price ) AS fprice,
ag.agent_name, DATE_FORMAT( o.date_added, '%d-%m-%Y') as dadded ,
offer_status
FROM i_offers_12 o
LEFT JOIN i_agents ag ON o.agents_id = ag.id
LEFT JOIN i_currencies c ON o.currencies_id = c.id
LEFT JOIN i_offers_details od ON ( o.id = od.offers_id AND od.languages_id = 1 )
LEFT JOIN i_offers_images oi ON ( oi.offers_id = o.id AND oi.o_id = '12' )
WHERE ( o.offer_status='active' OR o.offer_status='sold')
AND actions_id = '1'
AND c.id = o.currencies_id
AND o.counties_id = '2'
AND o.cities_id = '3'
AND o.offer_status='active'
GROUP BY o.id
ORDER BY offer_status, dadded
DESC
Note that you normally should group by ALL non summarized fields (o.*,
IF(pricet=2,c.currency_value*o.attributes_36*o.price,
c.currency_value*o.price) AS pprice, od.title, oi.image, ( c.currency_value * o.price ) AS fprice,
ag.agent_name, DATE_FORMAT( o.date_added, '%d-%m-%Y') as dadded ,
offer_status)
MySQL is not enforcing it, but other DB like Oracle does.
You can use a comma, like
ORDER BY supplier_city DESC, supplier_state ASC;
I believe you can write the SQL with
ORDER BY offer_status, dadded

How to translate SQL to LINQ?

sql
select * from (select * from tabla limit 1) as a inner join table b on a.id = b.id where a.id = id
LINQ
from s in tableA
join c in (from a in tableB where a.id==id select a).FirstOrDefault() on s.id equals c.id
where s.id == id
select s
I want to translate this sql to linq but failed. How can I do translate?
I think this will do it, but you should check what sql is being generated by linq.
a = tableA.FirstOrDefault();
//First option
tableB.Where(xb => xb.id = a.id)
.Select(xb => new {a = a, b = xb})
.Where(abx => abx.a.id == id)
//Second option
tableB.Select(xb => new {a = a, b = xb})
.Where(abx => abx.a.id == id && abx.a.id = abx.b.id)

LINQ with sub select query using sum and group by?

Can anyone help me with a LINQ query. I have converted most of it but i have a sub query in the stored procedure and i can't figure out how to do it..
basically this is the old stored procedure (truncated for ease)
SELECT M.Period AS 'Period' ,
C.Code AS 'Group' ,
C.ClientCode AS 'Code' ,
C.ClientName AS 'Name' ,
( SELECT SUM(Amount) AS Expr1
FROM M
WHERE ( ClientCode = C.ClientCode )
GROUP BY ClientCode
) AS 'Amount' ,
As you can see from above the sub query is like so
SELECT SUM(Amount) AS Expr1
FROM M
WHERE ( ClientCode = C.ClientCode )
GROUP BY ClientCode
) AS 'Amount'
So i have done all my joins and i have this so far and it works.
var test = from c in C join h in H on c.Code
equals h.Code join m in M on c.ClientCode
equals m.ClientCode
select new
{
Period=m.Period,
Group=c.Code,
Code= c.ClientCode,
Name= c.ClientName,
<-- Here is where i need the sub select query above -->
};
But i am at a loss of how to do the subquery. The name of the column will be Amount as you are able to see in the old stored procedure.
I would appreciate any feedback or help
THanks
Im not sure on that last part of your SQL query but I am assuming something like this
SELECT M.Period AS 'Period' ,
C.Code AS 'Group' ,
C.ClientCode AS 'Code' ,
C.ClientName AS 'Name' ,
( SELECT SUM(Amount) AS Expr1
FROM M
WHERE ( ClientCode = C.ClientCode )
GROUP BY ClientCode
) AS 'Amount'
from C inner join M on C.ClientCode = M.ClientCode
so your LINQ will be this
var test = from c in db.C
select new {
Period = c.M.Period,
Group = c.Code,
Code = c.ClientCode,
Name = c.ClientName,
Amount = (System.Int32)
((from m0 in db.M
where
m0.ClientCode == c.ClientCode
group m0 by new {
m0.ClientCode
} into g
select new {
Expr1 = (System.Int32)g.Sum(p => p.Amount)
}).First().Expr1)
}

Resources