Query using CASE, WHEN, THEN in postgresql not working - sql

I have three tables, tbl_doctors_details, tbl_time and tbl_token.
I have to select the details from tbl_time or tbl_token. That is if for particular doctor in hospital have t_type is time then select from tbl_time else select from tbl_token.
For example, for doctor_id is 100 and hospital_id 1, the t_type is time. So for this user, details should select from tbl_time table.
Below is the sample structure and data of three tables:
How can I use CASE condition in query here?
I tried:
SELECT *
FROM
( SELECT * CASE WHEN t_type= 'time' FROM dbname.tbl_doctors_details t1 THEN
dbname.tbl_time t2
ELSE
dbname.tbl_token t2
WHERE t1.hospital_id=t2.hospital_id AND t1.doctor_id=t2.doctor_id);
I know the query is not working, but how can I make the query working?

You need to join both tables using two LEFT JOINs and then COALESCE to find the matching data:
SELECT t1.*,
colaesce(t_time.hospid, t_token.hospid),
colaesce(t_time.start, t_token.start)
FROM dbname.tbl_doctors_details t1
LEFT JOIN dbname.tbl_time t_time
ON t1.doctor_id=t_time.doctor_id
AND t1.t_type= 'time'
LEFT JOIN dbname.tbl_token t_token
ON t1.doctor_id=t_token.doctor_id
AND t1.t_type= 'token';

Use CASE WHEN in your SELECT and LEFT JOIN both tables. In both LEFT JOIN use the condition of t_type to join on the tables. In your SELECT you can now check whether table t1 or t2 was joined and select the preferred column. Here's a sample (the selected column is just a sample to illustrate):
SELECT CASE WHEN t1.id IS NULL THEN t2.id ELSE t1.id END AS joined_id
FROM tbl_doctors_details as tbl_base
LEFT JOIN tbl_time t1 ON t1.t_type = 'time' AND t1.doc_id = tbl_base.doc_id
LEFT JOIN tbl_token t2 ON t2.t_type = 'token' AND t2.doc_id = tbl_base.doc_id

Serious smell of doing homework for someone here.. Meh
SELECT
doctors.*
, CASE
WHEN doctors.type = 'time' THEN time.start
ELSE token.start
END AS start
FROM
doctors
LEFT OUTER JOIN time
ON time.doc_id = doctors.doc_id
AND time.hospital_id = doctors.hospital_id
AND doctors.t_type = 'time'
LEFT OUTER JOIN token
ON token.doc_id = doctors.doc_id
AND token.hospital_id = doctors.hospital_id
AND doctors.t_type = 'token'

Related

Editing result of joined/concatenated table result in PSQL

i have a sql query i'm running that joins & concatenates multiple tables, resulting in new columns, etc. I want to easily edit these fresh column values by double-clicking into the empty portions, like usual, but i read when joining tables they become read-only. I also wanted to attempt a regular INSERT cmd but don't understand what the table name is, since its all resulted from a lengthy query. How can i edit this queried table?
Below, i have pasted the query. For example, this spits out a new column change_products, and i want to edit those values but as mentioned above, cannot after joining/concatenating. Thanks!
SELECT change_ticket,
change_product,
change_desc,
change_state,
security_bulletin,
change_assigned_to,
affected,
remediated
FROM change_tickets t1
LEFT JOIN change_product_link t2 ON t1.id = t2.chg_id
LEFT JOIN (SELECT id, concat(product_name, ' ', product_version) AS change_product FROM products) chg_product ON t2.product_id = chg_product.id
LEFT JOIN change_sb_link t4 ON t1.id = t4.chg_id
LEFT JOIN security_bulletins t5 ON t5.id = t4.sb_id
LEFT JOIN product_sb_link t6 ON t5.id = t6.sb_id
LEFT JOIN (SELECT id, concat(product_name, ' ', product_version) AS affected FROM products) aff_soft ON t6.affected_software_id = aff_soft.id
LEFT JOIN (SELECT id, concat(product_name, ' ', product_version) AS remediated FROM products) rem_soft ON t6.remediated_software_id = rem_soft.id
WHERE change_state NOT IN ('Cancelled', 'Closed - Successful', 'Post-Verify') OR change_state IS NULL
ORDER BY 1

The multi-part identifier could not be bound - SQL Server 2014

I am trying to solve the error in the below query
Yes I have checked many same questions but still can not figure out the solution
The error:
The multi-part identifier "Table_2.id" could not be bound.
When I remove the inner join the query runs perfectly fine
I have to solve this problem without turning it into explicit joins because i have so many dynamic filtering which add and x=y clauses to the end of the query
Thank you
SELECT TOP 10 username,
NAME,
table_1.authoritylevel,
totalcount,
avglevel,
table_2.pokemonid,
pokemonlevel,
table_2.id,
pokemonexp,
battlecount,
battlevictorycount,
table_1.userid
FROM table_1,
table_2,
table_3,
table_4
LEFT OUTER JOIN (SELECT Count(table_5.offereruserid) AS OfferCount,
table_5.offereduserspokemonsid
FROM table_5
GROUP BY offereduserspokemonsid) innerQuestion
ON innerQuestion.offereduserspokemonsid = table_2.id
WHERE table_3.pokemonid = table_2.pokemonid
AND pokemonplace = 'trade'
AND table_4.pokemonid = table_2.pokemonid
AND table_2.userid = table_1.userid
AND table_2.userid != 1
If you are keen on keeping the implicit joins, you could split your query into several result sets using WITH. According to this article, you can no longer do "implicit outer joins." Give this a try:
WITH OfferCounts as
(
SELECT Count(table_5.offereruserid) AS OfferCount, table_5.offereduserspokemonsid
FROM table_5
GROUP BY offereduserspokemonsid
),
EverythingElse AS
(
SELECT TOP 10 username,
NAME,
table_1.authoritylevel,
totalcount,
avglevel,
table_2.pokemonid,
pokemonlevel,
table_2.id,
pokemonexp,
battlecount,
battlevictorycount,
table_1.userid
FROM table_1,
table_2,
table_3,
table_4,
WHERE table_3.pokemonid = table_2.pokemonid
AND pokemonplace = 'trade'
AND table_4.pokemonid = table_2.pokemonid
AND table_2.userid = table_1.userid
AND table_2.userid != 1
)
Select *
From EverythingElse t1
left join OfferCounts t2 on t1.offereduserspokemonsid = t2.id
The specific problem comes from the use of implicit joins first and then an explicit join. Lesser lines of code is not a very good reason to use implicit joins, specially since it's deprecated.
Another considerations would be to use table aliases, and also to prefix every column with the corresponding table alias, even if the column is unique between those tables for readability and a code that's easier to maintain.
You are also missing the GROUP BY needed for your aggregation function. All in all, the fixed code would be:
SELECT TOP 10 username,
NAME,
T1.authoritylevel,
totalcount,
avglevel,
T2.id,
T2.pokemonid,
pokemonlevel,
pokemonexp,
battlecount,
battlevictorycount,
T1.userid,
Count(T5.offereruserid) AS OfferCount
FROM Table_1 T1
INNER JOIN Table_2 T2
ON T1.userid = T2.userid
INNER JOIN Table_3 T3
ON T2.pokemonid = T3.pokemonid
INNER JOIN Table_4 T4
ON T2.pokemonid = T4.pokemonid
INNER JOIN Table_5 T5
ON T5.offereduserspokemonsid = T2.id
WHERE pokemonplace = 'trade'
AND T2.userid != 1
GROUP BY username,
NAME,
T1.authoritylevel,
totalcount,
avglevel,
T2.id,
T2.pokemonid,
pokemonlevel,
pokemonexp,
battlecount,
battlevictorycount,
T1.userid;
But, as I said, I suggest that you add the corresponding prefixes to those columns.

How to exclude records based on second table (using JOIN)

I think this is simple, but not so today...
I have two tables The first has a column with data from the second.
T1 has Column1 value = "Created"
T2 has Column1 Value = "Created" and Column2 Value = "OPEN"
So the idea is to return every row from table 1 where column 2 of table 2 = "OPEN"
This si the current SELECT
SELECT tblCustIncidents.IncidentID, tblCustIncidents.EntryDateTime, tblCustIncidents.Title, tblCustIncidents.StatusType, tblCustIncidents.Summary, tblMaintStatusTypes.StatusDescr
FROM tblCustIncidents LEFT JOIN
tblMaintStatusTypes
ON tblCustIncidents.StatusType = tblMaintStatusTypes.StatusType;
I thought I could just use WHERE but I am not clear on the location of the WHERE or even if it will work... I've been looking more than a little while. I'll keep looking and hope someone can point me tot he right method/answer/post etc. Thanks.
In the screenshot of the returned data the last column is in both tables. The second table has a column indictaing if the item is open or closed. SO I would want all records in the snippet NOT to appear... I have tried this Select statement...
SELECT tblCustIncidents.IncidentID, tblCustIncidents.EntryDateTime, tblCustIncidents.Title, tblCustIncidents.StatusType, tblCustIncidents.Summary, tblMaintStatusTypes.StatusDescr
FROM tblCustIncidents LEFT JOIN tblMaintStatusTypes ON tblCustIncidents.StatusType = tblMaintStatusTypes.StatusType
WHERE tblMaintStatusTypes.OpenOrClosedType = 'Open';
OK I figured out access is picky... so I have tried this...
SELECT tblCustIncidents.IncidentID,
tblCustIncidents.EntryDateTime,
tblCustIncidents.Title,
tblCustIncidents.StatusType,
tblCustIncidents.Summary,
tblMaintStatusTypes.StatusDescr
FROM tblCustIncidents
inner join (SELECT tblCustIncidents.IncidentID,
tblCustIncidents.EntryDateTime,
tblCustIncidents.Title,
tblCustIncidents.StatusType,
tblCustIncidents.Summary,
tblMaintStatusTypes.StatusDescr
FROM tblCustIncidents)
ON (tblCustIncidents.StatusType = tblMaintStatusTypes.StatusType AND tblMaintStatusTypes.OpenOrClosedType = 'Open');
SELECT t1.*
FROM table1 t1
JOIN table2 t2
ON t1.Column1=t2.Column1
WHERE t2.column2='OPEN'
Based on your query you just need to add clause to the join and than change join from left to inner, otherwise you will still get all rows from table 1.
SELECT tblCustIncidents.IncidentID
,tblCustIncidents.EntryDateTime
,tblCustIncidents.Title
,tblCustIncidents.StatusType
,tblCustIncidents.Summary
,tblMaintStatusTypes.StatusDescr
FROM tblCustIncidents
INNER JOIN tblMaintStatusTypes
ON tblCustIncidents.StatusType = tblMaintStatusTypes.StatusType
WHERE tblMaintStatusTypes.Column2 = 'OPEN'

Getting a ton of duplicates? Left Join incorrect?

Here is a sample of my query:
SELECT ...
TRIM(eml.fxeml1) as "Email Address"
FROM pfship
LEFT JOIN mstfxem fax
ON fax.fxco=pfship.cshco AND fax.fxdiv=pfship.cshdiv AND fax.fxsold=pfship.cshsld
AND fax.fxtype='C' AND TRIM(fax.fxfax1) <> '' AND fax.fxdept LIKE '*F%'
LEFT JOIN mstfxem eml
ON eml.fxco=pfship.cshco AND eml.fxdiv=pfship.cshdiv AND eml.fxsold=pfship.cshsld
AND eml.fxtype='C' AND TRIM(eml.fxeml1) <> '' AND eml.fxdept LIKE '*E%'
WHERE ((pfship.cshco || '/' || pfship.cshdiv) = ?)
AND (? = '*ALL' OR CAST(cshsld AS CHAR(15)) = ?)
AND ...
ORDER BY TRIM(cshnme)
This query should return 9 records. When I remove:
LEFT JOIN mstfxem fax
ON fax.fxco=pfship.cshco AND fax.fxdiv=pfship.cshdiv AND fax.fxsold=pfship.cshsld
AND fax.fxtype='C' AND TRIM(fax.fxfax1) <> '' AND fax.fxdept LIKE '*F%'
LEFT JOIN mstfxem eml
ON eml.fxco=pfship.cshco AND eml.fxdiv=pfship.cshdiv AND eml.fxsold=pfship.cshsld
AND eml.fxtype='C' AND TRIM(eml.fxeml1) <> '' AND eml.fxdept LIKE '*E%'
I get 9 records, but with it I get 360 records. What is wrong with my join?
Thanks
I think the problem is that 1 person can have many emails or faxes, how do I group the results into 1 string per record so I end up with only 9 records?
Nothing is wrong with your join, you have a one to many relationship between the tables.
Depending on what you need there are several techniques. First is the derived table. Write a query to pick out only one record from the one to many table (your requirements should specify which record to pick). Join to that instead. OR you may be able to put further conditions on the left join to get only one record. Some examples of these techniques:
select t1.field1, t2.email
from table1 t1
join (select myid, max(email) as email from table2 group by myid) t2
on t1.myid = t2.myid
Or
select t1.field1, t2.email
from table1 t1
Left join from table2 t2
on t1.myid = t2.myid and t2.active = 1
Or if you want all of the emails in a comma delimited list, that code is database specific and you would need to let us know which database backend you are using.

SQL - displaying zero results

I am looking to display a 'O' or 'No results found' when no records are found based off my query but can't get it right. I think the problem comes from that I am trying to display information about the records I am counting along with how many there are that fit the criteria. Perhaps its not the count that I need to change with ISNULL but something to modify the result if no rows are outputted.
Thanks for any help in advance.
select t3.countyname, t2.titleunitname, t1.transdesc, count (isnull(t3.orderkey,0)) as c1
from tblorder as t3
left join qryOrderRecord1 as t1 on t3.OrderKey = t1.OrderKey
left join qrytitleunits as t2 on t3.titleunitnum = t2.titleunitnum
WHERE t1.transdesc = 'LETTERS'
AND (t3.OrderDateTime between '7/7/2010' AND '7/7/2010')
AND t3.countyname = 'Frankfurt'
AND t2.titleunitname = 'Maxwell'
group by t3.countyname,t1.transdesc, t2.titleunitname
That count(isnull(column, 0)) is the same as count(1) or count(*). See this question for the why...
Count(*) vs Count(1)
Maybe you want count(t1.orderkey)? This would not count any null t1.orderkey's.
I think you need to count t1.orderkey t3 is on the left side of the outer join so it is the t1.orderkey values that will be NULL.
Also I moved the Filters on t1 and t2 into the JOIN conditions not the WHERE clause
If that doesn't do the trick providing some sample data in your question will help.
SELECT t3.countyname,
t2.titleunitname,
t1.transdesc ,
COUNT(t1.orderkey) AS c1 /*As dotjoe's answer suggests*/
FROM tblorder AS t3
LEFT JOIN qryOrderRecord1 AS t1
ON t3.OrderKey = t1.OrderKey
AND t1.transdesc = 'LETTERS'
LEFT JOIN qrytitleunits AS t2
ON t3.titleunitnum = t2.titleunitnum
AND t2.titleunitname = 'Maxwell'
WHERE t3.OrderDateTime BETWEEN '7/7/2010' AND '7/7/2010' /*Seems odd! Should these be
different dates?*/
AND t3.countyname = 'Frankfurt'
GROUP BY t3.countyname,
t1.transdesc ,
t2.titleunitname
Give this a shot.
select t3.countyname, t2.titleunitname, t1.transdesc, count (isnull(t3.orderkey,0)) as c1
into #Tmp
from tblorder as t3
left join qryOrderRecord1 as t1 on t3.OrderKey = t1.OrderKey
left join qrytitleunits as t2 on t3.titleunitnum = t2.titleunitnum
where t1.transdesc = 'LETTERS'
AND (t3.OrderDateTime between '7/7/2010' AND '7/7/2010')
AND t3.countyname = 'Frankfurt'
AND t2.titleunitname = 'Maxwell'
group by t3.countyname,t1.transdesc, t2.titleunitname
if ##ROWCOUNT > 0
select *
from #Tmp
else
select 'No Results Found.'