How to write subquery in Criteria - group-by

I have a SQL like this:
Select tbl.id, tbl.name
From
(select table1.id, table1.name
from table1
inner join table2 on table1.id = table2.id
order by table2.priority
) tbl
group by table1.id
order by table1.name
What I'm trying to achieve is to first sort (order by table2.priority), and then get the record with table1.id, name with highest priority.
Note, MAX(table2.priority) doesn't work here, because table1 to table2 is one to many, and for one table1 record, table2 can have N records with the highest priority = 1, where another table1 record with highest priority = 3.

If you only need one record from the result, and they are in order such that the record you need is at the end (or beginning) of the sort, simply limit the results to one. i.e:
SELECT tbl.id, tbl.name
FROM (
SELECT table1.id, table1.name
FROM table1
INNER JOIN table2 ON table1.id = table2.id
ORDER BY table2.priority
) tbl
GROUP BY table1.id
ORDER BY table1.name
LIMIT 1;
Note that depending on the order, you could specify ASC or DESC to ensure the correct record is the one you retrieve.

Related

“Not exists” across multiple joins

I am learning sql (postgres) and id like to find values that do not exist.
I have a table, table 1 with ids and i want to find those ids that are not in table 4.
I have to join between 3 tables as table 1 holds id and table 4 contact_id (not the same number)
The tables 2,3 need to be joined as that connects the ids.
So how do i do that with “not exists”?
Select t1.id, table4.contact_id
From table1 t1
Join table2 using(id)
Join table3 using(id)
Join table4 using(contact_id)
Where not exists (
Select 1
From table4
Where table4.contact_id=t1.id
);
It returns no values, but should
No error msg…
I have thinking error i assume
Your query probably returns no values because you join table4 on contact_id and then you exclude in the WHERE clause the rows which come from this join.
To find values that don't exist, you can usually use LEFT JOIN or RIGHT JOIN or FULL OUTER JOIN and then filter the rows with NULL values in the WHERE clause.
Try this :
SELECT t1.id
FROM table1 t1
LEFT JOIN table2 t2 using(id)
LEFT JOIN table3 t3 using(id)
LEFT JOIN table4 t4 using(contact_id)
WHERE t4.contact_id IS NULL

TSQL select all columns from join with same names

If I have a query
select * into #tmp1 from dbo.t1 inner join dbo.t2 on t1.Sender_Id=t2.Id
I get an error
Column names in each table must be unique. Column name 'Id' in table '#tmp1' is specified more than once.
How can I do the same thing without resorting to
select t1.Id as t1id, t1.col2. ... t1.col30, t2.Id as t2id, ... t2.col40 as t2col40 from ...
notation.
I just need to quickly and manualy examine several tables, so I'd like to have a quick way of examining joins.
If you have to persist the result via select * into #tmp or want to create a view, every field name has to be unique and you will have to uses aliases for fields with identical names.
A simple query does not need unique names.
Yes, columns name must unique in select statement, in your case, you have for example two (02) id, one from tbl1, and the other one from tbl2, on esolution is list them as:
Select t1.id, t2.id
From tbl1 as t1 Inner Join tbl2 as t2 on t1.id = t2.id
Hope this help.
Or, if you have columns with same name in both tables, use this:
Select t1.*, t2.* From tbl1 as t1 Inner join tbl2 as t2 On t1.id = t2.id
Regards

select record from joined table if it exists

I'm working on a sql query that should 'coalesce' the records from 2 tables, i.e. if the record exists in table2, it should take that one, otherwise it should fall back to the values in table1.
In the example, table1 and table2 have just 2 fields (id an description), but obviously in reality there could be more.
Here's a small test case:
create table table1 (id int, description nvarchar(50))
create table table2 (id int, description nvarchar(50))
insert into table1 values (1, 'record 1')
insert into table1 values (2, 'record 2')
insert into table1 values (3, 'record 3')
insert into table2 values (1, 'record 1 modified')
insert into table2 values (2, null)
The result of the query should look like this:
1, "record 1 modified"
2, null
3, "record 3"
Here's what I came up with.
select
case when table2.id is not null then
table2.id else table1.id
end as Id,
case when table2.id is not null then
table2.description
else
table1.description
end as Description
-- etc for other fields
from table1
left join table2 on table1.id = table2.id
Is there a better way to achieve what I want? I don't think I can use coalesce since that would not select a null value from table2 if the corresponding value in table1 is not null.
How about:
SELECT t2.ID, t2.Description
FROM table2 t2
UNION ALL
SELECT t1.ID, t1.Description
FROM table1 t1
WHERE NOT EXISTS (SELECT *
FROM table2 t2
WHERE t2.ID = t1.ID)
The above query gets all the records from table 2 (including the case where description is NULL but the ID is populated), and only the records from table 1 where they don't exist in table 2.
Here's an alternative:
SELECT table2.*
FROM table1
RIGHT JOIN table2
ON table1.id = table2.id
UNION
SELECT table1.*
FROM table1
FULL OUTER join table2
ON table1.id = table2.id
WHERE table1.id NOT IN (SELECT id FROM table2)
--and table2.id not in (select id from table1)
You can add in that last line if you don't want ids that are only in table2. Otherwise I guess Stuart Ainsworth's solution is better (i.e. drop all the joins)
http://sqlfiddle.com/#!3/03bab/12/0

ordering by rows

OK so I have a query I am trying to build.. I have 2 tables, table1 has a bunch of regular records as normal with a unique ID (auto increment) and table2 has records that include some of those ids from table1. I am trying to order by the highest records with that same ID in table1.. Heres what I've got:
SELECT * FROM table1
WHERE table1.status = 1
AND (SELECT COUNT(*) FROM table2 WHERE table2.tbl1_id = table1.id)
ORDER BY table1.id DESC
Thanks :)
SELECT table1.id
FROM table1
LEFT JOIN table2 ON table2.tbl1_id = table1.id
WHERE table1.status = 1
GROUP BY table1.id
ORDER BY COUNT(table2.tbl1_id) DESC
Try this:
SELECT a.*, b.cnt
FROM table1 a LEFT JOIN
(
SELECT tbl1_id, COUNT(*) cnt
FROM table2
GROUP BY tbl1_id
) b
ON a.id = b.tbl1_id
WHERE table1.status = 1
ORDER BY cnt DESC

How to use "as" to set alias for joined tables in oracle 10

I wrote this, and it is wrong syntax, help me fix it, I want 'T' to be an alias of the result of the two inner joins.
select T.id
from table1
inner join table2 on table1.x = table2.y
inner join table3 on table3.z = table1.w as T;
You cannot use aliases to name the "entire" join, you can, however, put aliases on individual tables of the join:
select t1.id
from table1 t1
inner join table2 t2 on t1.x = t2.y
inner join table3 t3 on t3.z = t1.w
In the projection, you will have to use the alias of the table, which defines the id column you are going to select.
You can't directly name the result of a join. One option is to use a subquery:
select T.id
from (
select *
from table1
inner join table2 on table1.x = table2.y
inner join table3 on table3.z = table1.w
) T
Another option is subquery factoring:
with T as (
select *
from table1
inner join table2 on table1.x = table2.y
inner join table3 on table3.z = table1.w
)
select T.id
from T