How to join tables using CASE WHEN in postgresql? - sql

I have a PostgreSQL query like below and I want to join a new table to that when rateid>100
CASE WHEN rateid<100 Then
Select * FROM rate as A, plan AS B, room AS C
WHERE A.id=B.rateid
AND B.roomid=C.id
ELSE
Select * FROM rate as A, plan AS B, room AS C, hotel AS D
WHERE A.id=B.rateid
AND B.roomid=C.id
AND C.hotelid=D.id
END
Can I know is there any way to join hotel table when rateid>100?

In your question you say "when rateid>100", I assume you mean "rateid>=100" because in the code you use "rateid<100"
I also changed the old-style to new-style joins.
The on-clause tells SQL what to join, so adding "rateid>=100" should solve the problem (When I understand your question correctly)
select
*
from
rate as A,
inner join plan as B on
A.id = B.rateid
inner join room as C on
B.roomid = C.id
and rateid >= 100

Related

Query throws ORA-00904 Invalid Identifier when using joins

I've come across some weird behavior that's preventing me from setting up a query in the way I'd like to. Would appreciate any ideas. If there's any information about the tables that would be helpful, please let me know. I looked through them and nothing jumped out at me that might cause this but nor did I know what I was looking for. Here is the behavior.
This works fine:
Select *
From
SCHEMA_A.TABLE_A a,
SCHEMA_B.TABLE_B b,
SCHEMA_C.TABLE_C c,
SCHEMA_A.TABLE_D d
Where
b.friend_id = c.friend_id
AND a.group_id = d.group_id
AND b.group_cd = d.group_cd
But this returns ORA-00904: b.friend_id = c.friend_id: invalid identifier
Select *
From
SCHEMA_A.TABLE_A a,
SCHEMA_B.TABLE_B b,
SCHEMA_A.TABLE_D d
Join
SCHEMA_C.TABLE_C c
On
b.friend_id = c.friend_id
Where
a.group_id = d.group_id
AND b.group_cd = d.group_cd
This returns ORA-00904: b.group_cd = d.group_cd: invalid identifier
Select *
From
SCHEMA_A.TABLE_A a,
SCHEMA_B.TABLE_B b
Join
SCHEMA_C.TABLE_C c
On
b.friend_id = c.friend_id
Join
SCHEMA_A.TABLE_D d
On
a.group_id = d.group_id
AND b.group_cd = d.group_cd
And this works again:
Select *
From
SCHEMA_A.TABLE_A a,
SCHEMA_B.TABLE_B b
Join
SCHEMA_C.TABLE_C c
On
b.friend_id = c.friend_id
Join
SCHEMA_A.TABLE_D d
On
b.group_cd = d.group_cd
Where
a.group_id = d.group_id
Try with the using keyword which is designed for join on same column name
Select *
From
SCHEMA_A.TABLE_A a,
SCHEMA_B.TABLE_B b
Join
SCHEMA_C.TABLE_C USING(friend_id)
Join
SCHEMA_A.TABLE_D d using(group_id)
where b.group_cd = d.group_cd;
Also make sure that you execute the other query with the right users, as an user that does not have correct permission will throw invalid identifier.
Edit : The actual problem is that you are joining TABLE_C with TABLE_D but the join condition refer to TABLE_B change it to
Select *
From
SCHEMA_A.TABLE_A a,
SCHEMA_A.TABLE_D d,
SCHEMA_B.TABLE_B b
Join
SCHEMA_C.TABLE_C c using(friend_id)
Where
a.group_id = d.group_id
AND b.group_cd = d.group_cd;
Apply the same logic for other queries, when doing a join, you do not join to a group of table, but to the last table mentionned in the from clause therefore it did not have access to TABLE_B.
For other people that might have an invalid identifier error, make sure your database is not case sensitive, else make sure to use the right case.
I believe that you have run into the intricacy in SQL dealing with join scoping/precedence. Since I am not myself a database programmer, I can't really tell you why it works the way it does, but I do see some logic in the way the query parser is behaving.
In your first query, all the joins are cross joins. As a result, they should have the same precedence. So all the joined columns are known when the join is evaluated.
In the second query, you have a combination of cross joins and inner joins. If we assume that inner join has precedence over cross joins, then table c and d are joined before any other tables are added to the mix. So when you reference b.friend_id in the inner join, which is outside of the inner join, the query parser isn't able to use that column in evaluating the join.
In the third query, the inner join between tables b, c and d take precedence over the cross join. So column a.group_id isn't available in evaluating the inner join condition. When you take table a out of the inner join condition in the final query, the query no longer has a conflicting precedence.
The problem here is the mixing of join types. When you use comma-separated table in the FROM clause, each term is evaluated individually. Take the following example:
From
SCHEMA_A.TABLE_A a,
SCHEMA_B.TABLE_B b,
SCHEMA_A.TABLE_D d
Join
SCHEMA_C.TABLE_C c
On
b.friend_id = c.friend_id
The database is trying to resolve SCHEMA_A.TABLE_D d Join SCHEMA_C.TABLE_C c On b.friend_id = c.friend_id. Within this scope, b has no meaning (it's a separate term).
For your third version, I get "A"."GROUP_ID": invalid identifier, which is also in-line with this explanation.
Ultimately the lesson you should take from this is not to mix join types.

SQL Server Need Some Help Joins , please

I have 3 tables A, B, C. There is a relationship between tables A and C while there is a relationship between tables B and C . There is no relationship between A and B.
What I would really like to do is get a list of all the records from B when there are records in C related to B given a value from A .
Please let me know, if this is not clear enough
Thanks
you can right query something like this...
SELECT B.* FROM B
INNER JOIN C ON C.aa = B.aa
INNER JOIN A ON A.bb = C.bb
WHERE A.cc = #yourvalue
#yourvalue is your value on which bases you need to select the value from B table. if you need match mutliple values from A then you need to change bit of query some thing like this...
WHERE A.cc IN (#val1,#val2,#val3....,#valNth)
In this query we have used INNER JOIN so it will gives only those records which are common on both the tables LIKE if you only join B with C then it will give the records which are common in B and C and then you join A with C then it will give those records which are common in A and C.
So suppose in B there is records something like 1,2,3 and in C there is 2,3,4,5 and in A there is 1,3,4,5
so the output of above query (without applying WHERE cause) is 1,3 only because this is common in all three table A,B,C.
you can got more information for joins in sqlserver by refering this links..
http://blog.sqlauthority.com/2009/04/13/sql-server-introduction-to-joins-basic-of-joins/
http://www.dotnet-tricks.com/Tutorial/sqlserver/W1aI140312-Different-Types-of-SQL-Joins.html
http://www.aspdotnet-suresh.com/2011/12/different-types-of-joins-in-sql-server.html
Simple math dictates if there is a relationship between A and C, and a relationship between B and C, there is, albeit by association, a relationship between A and B (through C).
Thus you will need to join all three together, going from A, through C, to B:
SELECT B.*
FROM A
JOIN C ON A.x = C.x
JOIN B ON B.y = C.y
WHERE A.z = #z

Equivalent SQL Query using Cartesian Product Only

given 3 tables a : {id, name_eng}, b: {id, name_spa} and c: {id, name_ita}
which is the equivalent "product cartesian query" for this given one:
select
a.name_eng
b.name_spa
c.name_ita
from
a inner join b on a.id = b.id
left outer join c on a.id = c.id
I don't know what you want, a cartesian product would be this:
SELECT a.name_eng
b.name_spa
c.name_ita
FROM a
CROSS JOIN b
CROSS JOIN c
Or the implicit way:
SELECT a.name_eng
b.name_spa
c.name_ita
FROM a,b,c
If you want your previous query written with cartesian products (why??), then this should do (on SQL Server 2000):
SELECT a.name_eng
b.name_spa
c.name_ita
FROM a,b,c
WHERE a.id = b.id
AND a.id *= c.id
If I wasn't clear enough with the "why??", you shouldn't use implicit joins since hey are deprecated, you should always use proper explicit joins.

SQL SELECT and SUM from three

I have been cracking my head for hours on what I thought to be simple SQL SELECT command. I searched every where and read all questions related to mine. I tried an SQL Command Builder, and even read and applied complete series of SQL tutorials and manuals to try to build it from scratch understanding it (which is very important for me, regarding next commands I'll eventually have to build...).
But now I'm just stuck with the results I want, but on separates SELECT commands which I seem to be unable to get together !
Here is my case : 3 tables, first linked to the second with a common id, second linked to the third with another common id, but no common id from the first to the third. Let's say :
Table A : id, name
Table B : id, idA, amount
Table C : id, idB, amount
Several names in Table A. Several amounts in Table B. Several amounts in Table C. Result wanted : each A.id and A.name, with the corresponding SUM of B.amount, and with the corresponding SUM of C.amount. Let's say :
A.id
A.name
SUM(B.amount) WHERE B.idA = A.id
SUM(C.amount) WHERE C.idB = B.id for each B which B.idA = A.id
It's okay for "the first three columns", and "the first two columns and the fourth", both with a WHERE clause and/or a LEFT JOIN. But I can't achieve cumulating all fourth columns together without messing everything !
One could say "it's easy, just put an idA column in Table C" ! Should be easier, sure. But is it really necessary ? I don't think so, but I could be wrong ! So, I just please anyone (who I will give an eternal "SQL God" decoration) with SQL skills to answer laughing "That's so simple ! Just do that and you are gone ! Stupid little newbies..." ;)
Running VB 2010 and MS SQL Server
Thanks for reading !
Try this:
SELECT A.Id, A.Name, ISNULL(SUM(B.amount), 0) as bSum, ISNULL(SUM(C2.Amount), 0) as cSum
FROM A
LEFT OUTER JOIN B ON A.Id = B.idA
LEFT OUTER JOIN (SELECT C.idB, SUM(C.AMOUNT) AS Amount FROM C GROUP BY C.idB) AS C2 ON C2.idB = B.Id
GROUP BY A.Id, A.Name
Try this:
SELECT
a.id,
a.name,
sum(x.amount) as amountb,
sum(x.amountc) as amountc
from a
left join (
select
b.id,
b.ida,
b.amount,
SUM(c.amount) as amountc
from b
left join c
on b.id = c.idb
group by
b.id,
b.amount,
b.ida
) x
on a.id = x.ida
group by
a.id,
a.name
This should give you the result set you're looking for. It sums all C.Amount's for each B.id, then adds it all together into a single result set. I tested it with a bit of sample data in MSSQL, and it works as expected.
Select a.id, a.name, sum(b.amount), sum(c.amount)
from a inner join b on a.id = b.idA
inner join c on b.id = c.idB
group by a.id, a.name
You need to add them separately:
select a.id, a.name, (coalesce(b.amount, 0.0) + coalesce(c.amount, 0.0))
from a left outer join
(select b.ida, sum(amount) as amount
from b
group by b.ida
) b
on a.id = b.ida left outer join
(select b.ida, sum(amount) as amount
from c join
b
on c.idb = b.id
group by b.ida
) c
on a.id = c.ida
The outer joins are to take into account when b and c records don't both exist for a given id.

Joining One table to many using Joins

In this question it's finally clicked how to write joins between multiple tables, where they link in a line e.g.
Table A - Table B - Table C
Where Table A references Table B, and Table B references Table C and so on.
What I still don't understand is how to reference the situation where Table A references Table B as above and also reference Table D.
In implicit Joins I can get the following to work, but want to move it to explicits...
SELECT a.name, b.office, c.firm, d.status
FROM job a, depts b, firms c, statuses d
WHERE a.office = b.ref
AND b.firm = c.ref
AND a.status = d.ref
Any tips?
SELECT
a.name,
b.office,
c.firm,
d.status
FROM
job a
JOIN depts b ON a.office = b.ref
JOIN firms c ON b.firm = c.ref
JOIN statuses d ON a.status = d.ref
That's as detailed as I could get on such an obscure question. You didn't describe what exactly does "link" mean in your case. So I don't know, maybe you need left join.