My table looks like this, let's call it Table1:
ID | value | formID
----------------------
25 Business 1001
16 John 1001
5 2/20/17 1001
30 FormXYZ 1001
25 Nursing 2345
16 Sam 2345
5 1/15/17 2345
30 FormXYZ 2345
25 Tech 4500
16 Sam 4500
5 2/1/17 4500
30 FormC 4500
The ID is the unique identifier of that field:
25 = Department
16 = Name
5 = Date
30 = Form Name, we have multiple different Forms, and I just need FormXYZ data.
FormID is a unique ID for each form submitted, the form contains 3 fields.
I have been trying to write a single query that retrieves all data looking something like this if possible:
Department | Name | Date
Business John 2/20/17
Nursing Sam 1/15/17
Here is what I have been trying, nesting and CASE didn't seem to work right for me, so I am posting here and I am right back where I started at.
SELECT value
FROM Table1
WHERE ID = '25'
UNION ALL
SELECT value
FROM Table1
WHERE ID = '16'
UNION ALL
SELECT value
FROM Table1
WHERE ID = '5'
UNION ALL
SELECT value
FROM Table1
WHERE ID = '30' and value = 'FormXYZ'
One way to transpose data in SQL is to use case statements and roll up the data using a group by:
select
formID,
max(case when ID=25 then value else null end) as Department,
max(case when ID=16 then value else null end) as Name,
max(case when ID=5 then value else null end) as Date
from Table1
group by formID
This produces:
formid Department Name Date
1001 Business John 2/20/17
2345 Nursing Sam 1/15/17
4500 Tech Sam 2/1/17
You can add a where clause as needed. This should get the data in a single scan.
select dp.value as department,
n.value as name,
dt.value as date
from
(select formID, value from table1 where id = 25) as dp
inner join (select formID, value from table1 where id = 16) as n
on dp.formID = n.formID
inner join (select formID, value from table1 where id = 5) as dt
on dp.formID = dt.formID
inner join (select formID, value from table1 where id = 30) as f
on dp.formID = f.formID
where f.value = 'FormXYZ';
OR
select
case when id = 25 then value end as department,
case when id = 5 then value end as date,
case when id = 16 then value end as name
from table1
where formId in (select formID from table1
where id = 30 and value = 'FormXYZ')
and id in (5,16,25);
Related
I have a query as follows: Column c has a case statement for case 'P' and case 'M'.
The condition inside case 'P' is not working-> "and cs.case_id not in (SELECT case_id FROM case_status where (case_status_id = 16 and case_status_date < sysdate - 365)) AND cs.case_status_id = lk.id".
case Status for P is one to many so it's in a different table and for 'M' it's one to one so it's in the same cases table.
Also case status 'P' may or may not have record for a case.
SELECT
c.case_id,
c.id id,
lkp_alt.descr AS name,
(CASE WHEN c.case_type = 'P' THEN
(SELECT listagg(lk.descr, ', ') AS status
FROM case_status cs,
lkp_case_status lk
WHERE c.case_id = cs.case_id
and cs.case_id not in (SELECT case_id
FROM case_status
where (case_status_id = 16
and case_status_date < sysdate - 365)
)
AND cs.case_status_id = lk.id
GROUP BY c.case_id
)
ELSE (SELECT listagg(status, ', ') AS status
FROM (SELECT case_id,
lk.descr AS status
FROM lkp_hqmc_case_status lk
WHERE c.case_type = 'M'
AND lk.id = c.hamc_case_status
UNION
SELECT c.case_id,
lk.descr AS status
FROM lkp_fl_case_status lk
WHERE c.case_type = 'M'
AND lk.id = c.fl_case_status
)
GROUP BY case_id
)
END
) AS status
from cases c,
lkp_alt_show_cause_authority lkp_alt
WHERE c.ascAt = lkp_alt.id(+)
AND c.delete_date IS NULL
and not (nvl(c.hamc_case_status,0) = 8
and c.CLOSE_DATE < sysdate - 365
)
ORDER BY c.case_id desc
Case Table
id name hamc_case_status case_type
1 AAA 1 P
2 BBB 1 P
3 CCC 1 P
4 DDD 1 P
case_status
1 16 01-NOV-19 03.42.37.420000000 PM
1 5 01-NOV-19 03.42.37.420000000 PM
2 1 18-NOV-19 12.36.11.268000000 PM
2 3 18-NOV-19 12.36.11.268000000 PM
3 5 18-NOV-21 12.36.11.268000000 PM
3 16 18-NOV-21 12.36.11.268000000 PM
lkp_alt_show_cause_authority
id desc
1 TEST
2 TEST1
lkp_hqmc_case_status
id descr
1 status
2 status1..
8 Closed
lkp_fl_case_status
id descr
1 fstatus1
2 fstatus2
lkp_case_status
id Descr
1 Active
2 Intermediate
3 InActive
5 Prep
16 Closed
The output should show as follows:
Result:
id name status
2 BBB Active, InActive
3 CCC Prep, Closed
4 DDD
It shouldnt pull case with id = 1 since the case closed status 16 is in '01-NOV-19'
Output I get with this query is:
id name status
1 null
2 BBB Active, InActive
3 CCC Prep, Closed
4 DDD
It is a legacy application with 150 fields and multiple joins on reporting. I cannot change query with 'outer join'.
I have to use same format of tablea, tableb and use (+) for joins.
Thanks in advance.
I'm having a trouble writing a query in ORACLE. I have a Table that contains values. for example:
ID quantity partID
123 50 10
100 20 10
100 30 11
123 null 8
456 null 100
789 25 123
456 50 9
I want to get all rows that has same ID but quantities to be 50 and null (exact same pairs of 50 and null only). for the given example I would like to get:
ID quantity partID
123 50 10
123 null 8
456 50 9
456 null 100
I tried inner join but it doesn't provide the exact output as expected.
You may try :
select ID, quantity, partID
from tab
where ID in
(
select ID
from tab
where nvl(quantity,50)=50
group by ID
having count(distinct nvl(quantity,0) )>1
);
ID QUANTITY PARTID
123 50 10
123 (null) 8
456 (null) 100
456 50 9
SQL Fiddle Demo
P.S. you may get the same results by commenting out having count(ID)=2 also but for those cases there may not exist one of 50 or null for values of quantity.
You can use exists:
select t.*
from t
where (t.quantity = 50 and
exists (select 1 from t t2 where t2.id = t.id and t2.partid = t.partid and t2.value is null)
) or
(t.quantity is null and
exists (select 1 from t t2 where t2.id = t.id and t2.partid = t.partid and t2.value = 50)
) ;
I have three tables in Postgresql, for a biological classification system.
table lang (languages)
id name
1 português
2 english
-------------------------------
table taxon (biological groups)
id name
...
101 Mammalia
-------------------------------
table pop (popular names)
id tax lang pop
...
94 101 1 mamíferos
95 101 2 mammals
I want to get
id name namePT nameEN
101 Mammalia mamíferos mammals
but my join is giving me
id name pop
101 Mammalia mamíferos
101 Mammalia mammals
select t.id,name,pop from taxon t
left join pop p on p.tax = t.id
where t.id = 101
How can I get the desired result in a single row?
If you are happy to change query every time you add a new language then this query will do the trick:
select t.id,name,pe.pop as eng_pop, pp.pop as port_pop
from taxon t
left join pop pe on pe.tax = t.id and pe.lang = 1
left join pop pp on pp.tax = t.id and pp.lang = 2
where t.id = 101
You could use this
SELECT t.id, t.name,
MAX(CASE WHEN p.lang = 1 THEN p.pop END) AS namePT,
MAX(CASE WHEN p.lang = 2 THEN p.pop END) AS nameEN
FROM taxon t
LEFT JOIN pop p
ON p.tax = t.id
GROUP BY t.id, t.name;
Here's how I got the results:
with base as (
select t.id, t.name,
case when lang = 1 then 'mamiferos' else null end as namePT,
case when lang = 2 then 'mamals' else null end as nameEN
from taxon t
left join pop p on t.id = p.tax
group by 1,2,3, p.lang
)
select
distinct id,
name,
coalesce(namept,'mamiferos',null) as namept,
coalesce(nameen,'mamals',null) as nameen
from base
where id = 101
group by id, name, namept, nameen;
id | name | namept | nameen
-----+----------+-----------+--------
101 | Mammalia | mamiferos | mamals
(1 row)
I have a WHERE clause in a query that needs to see whether the latest entry in a related table meets certain criteria. However, I'm not able to inject the PK of the top query directly into the clause for a number of different reasons.
Is there any way to rewrite the following query to depend on the outer alias (ie. make ALIAS.pk work)? foo has a composite primary key.
(SELECT CASE WHEN EXISTS (
SELECT * FROM (
SELECT n.val1, n.val2 FROM (
SELECT * FROM foo f
WHERE f.val0 = 100 AND f.outerid = ALIAS.pk
ORDER BY f.date DESC
) n
WHERE n.rownum = 1
) t
WHERE t.val1 = 1 AND t.val2 = 2
) THEN 1 ELSE 0 END FROM dual) = 1
Edit: Outer table (bar):
id name city
1 Bob London
2 Mike Atlanta
3 Susan Toronto
Inner table (foo):
outerid date val1 val2 val100 fk1 fk2 fk3
1 2014-11-11 1 2 100 11 523 15
1 2014-11-11 1 2 101 14 12 87
1 2014-11-10 1 2 100 17 1667 12
2 2014-11-11 1 1 100 91 12 188
The primary key for foo is a composite key over fk1..3.
So what I need is to select the latest entry from foo that corresponds to a certain user and check that it has certain characteristics.
Edit 2:
SELECT CASE WHEN ({inner query})=1 THEN 1 ELSE 0 END WHERE id = 1 should return "1" SELECT SELECT CASE WHEN ({inner query})=1 THEN 1 ELSE 0 END WHERE id = 2 should return "0".
This may give you the output you require:
SELECT b.name
FROM bar b
INNER JOIN
(SELECT DISTINCT
f.outerid
FROM
(SELECT f.outerid
, f.val1
, f.val2
, f.date
, max(f.date) OVER
(PARTITION BY f.outerid
ORDER BY f.date) max_date
FROM foo f
WHERE f.val0 = 100) f
WHERE f.date = f.max_date
AND f.val1 = 1
AND f.val2 = 2) f
ON (f.outerid = b.id)
I have a query result that is almost perfect except for the fact that in the result I don't always have a complete series in my muli-series data that I am trying to eventually show in a report and chart.
NAME MONTH COST
----------------------------------------
name1 2 100
name1 3 80
name2 1 60
name3 2 30
----------------------------------------
Here is query:
select Name, month, count(*) as cost
from table1
group by name, month
order by month, name
What I have here isn't one simple set of data, but a series of data. For each month, I have a set of users and sales.
I can fix this on my application side by doing a few loops and getting the distinct values for Name and Month.
I'd like to learn how to create my Oracle query to get a result set that looks something like this
NAME MONTH COST
----------------------------------------
name1 1 0
name1 2 100
name1 3 80
name2 1 60
name2 2 0
name2 3 0
name3 1 0
name3 2 30
name3 3 0
----------------------------------------
You can do this with a cross join and then a left outer jon:
select n.name, m.month, coalesce(t.cost, 0) as cost
from (select distinct name from table t) n cross join
(select distinct month from table t) m left join
table t
on t.name = n.name and t.month = m.month
order by n.name, m.month;