i have 3 tables (A,B,C)
Table A -
ID Name
1 Sam
2 Manuel
3 Jane
Table B
ID Tab_A_ID Name
1 1 Meer
2 1 Kutti
3 2 Mikaro
Table C
ID Tab_B_ID Price
1 1 255.11
2 1 30.52
3 3 125.22
I need a query that shall pick up the top price for TableA-Name from TableC. So only 1 top price for 1 nae record.
e.g.-
Sam - 255.11
Manuel - 125.22
How can i get this?
To get the max price per entry in A:
SELECT a.Name,
MAX(c.price)
FROM a
INNER JOIN b
ON a.id = b.tab_a_id
INNER JOIN c
ON b.id = c.tab_b_id
GROUP BY a.id, a.name
To get the max price per entry A per entry B:
SELECT a.Name,
b.Name
MAX(c.price)
FROM a
INNER JOIN b
ON a.id = b.tab_a_id
INNER JOIN c
ON b.id = c.tab_b_id
GROUP BY a.id, b.id, a.name, b.name
Note that entries in A without corresponding entires in B or entries in B without corresponding entries in C will not appear in the result. Use LEFT JOIN if you want to include these in the result.
Related
i have following SQL table A in my database:
index, group, foo
1 A 2
2 A 2
3 A 0
4 A 1
5 B 2
6 B 1
7 C 1
There are few more groups and I need to write a query based on this filter table B. For each group in table A it's index should be equal or greater than index_egt from table B for the same group.
If the group is not listed in table B, the group won't be filtered.
index_egt, group
3 A
5 B
Expected result:
index, group, foo
3 A 0
4 A 1
5 B 2
6 B 1
7 C 1
Try this, the A.index>=B.index_egt will handle cases where the group is listed in TableB and the B.index_egt IS NULL will handle cases where the group is not listed:
SELECT
A.index,
A.group,
A.foo
FROM TableA AS A
LEFT JOIN TableB AS B ON A.group=B.group
WHERE A.index>=B.index_egt
OR B.index_egt IS NULL
select
a.*
from
A a
left join
B b ON b.group = a.group
where
a.index >= b.index_egt OR b.index_egt IS NULL
I always like this trick with coalesce
SELECT a.*
FROM a_table_with_no_name a
LEFT JOIN b_table_with_no_name b ON b.group = a.group
WHERE a.index >= COALESCE(b.index_egt,a.index)
I have two tables (Books, Authors) with ManyToMany relationship. I need SQL statement to retrieve books with authors, sorted by authors/books. Important thing is that I must retrieve them with pagination (offset ... fetch in sql).
One of the problem that when I join tables there are duplicates in results (of course) and offset/fetch can't be used for this results. Another problem the results must be sorted (not subpages but all books of course).
I have one idea: (it retrieves books sorted by author name and include pagination)
select b.id, b.title, a.name from Books b inner join Books_Authors ba
on ba.bookID = b.id inner join Authors a
on ba.authorID = a.id
where a.name in (select name from Authors order by name offset 9 rows fetch next 3 rows only)
order by a.name
But I think it's not efficient way.
Something like this?
select * from
(
select tmp1.*, ROW_NUMBER() over(partition by b.title, a.name order by b.id, a.id) rang2
from
(
select a.id, b.id, b.title, a.name, ROW_NUMBER() over(partition by b.title, a.name order by b.id, a.id) rang
from Books b inner join Books_Authors ba on ba.bookID = b.id
inner join Authors a on ba.authorID = a.id
) tmp1 where rang=1
) tmp2
where rang2 between 3 and 9
order by title, name
table1
sno exam questions time_duration
1 unit test 1 10
2 mock 1 2 10
3 mock2 5 10
4 mock3 6 6
table2
qid answer user_attempt_option
1 1 1
2 2 3
2 3 4
3 4 1
3 1 2
3 2 3
3 3 1
(My question has been asked a lot of times with two tables involved, and has been answered here, here and here. But I can't figure out how to do the same with three tables involved.)
I have three tables, A, B and C, where A has many B and B has many C. I want to join these tables and select zero or one rows per A, which one should be based on a condition in C.
Example, assume that:
SELECT
a.aId
,b.bId
,c.cId
FROM
a
INNER JOIN b ON b.aId=a.aId
INNER JOIN c ON c.bId=b.bId
WHERE
c.someColumn='foo'
...yields the following result:
aId bId cId
=== === ===
1 11 101
1 12 102
1 12 103
2 21 201
2 21 203
2 22 202
...then I would like to, for instance, retrieve two distinct A-rows, the ones with highest cId.
aId bId cId
=== === ===
1 12 103
2 21 203
You can use ROW_NUMBER:
WITH Cte AS (
SELECT
a.aId,
b.bId,
c.cId,
rn = ROW_NUMBER() OVER (PARTITION BY a.aId ORDER BY c.cId DESC)
FROM a
INNER JOIN b
ON b.aId = a.aId
INNER JOIN c
ON c.bId = b.bId
WHERE c.someColumn = 'foo'
)
SELECT
aId, bId, cId
FROM Cte
WHERE rn = 1
I have two tables with schema and data as below. Table A has an id and an associated name. Table B associates the id from Table A with a price and otherAttr. For each entry in Table A, there may be multiple entries with different prices in Table B, but otherAttr is the same for each entry.
Given an id for Table A, I would like to select the name, otherAttr, and the minimum price.
The below query returns multiple results, I need to write a query that will return a single result with the minimum price.
SELECT a.name, b.price, b.otherAttr
FROM A a
LEFT Join B b on b.idFromA = 1
WHERE a.id = 1
Table A Table B
id | name idFromA | price | otherAttr
-------- ---------------------------
1 | A 1 | 200 | abc
2 | B 1 | 300 | abc
1 | 400 | abc
2 | 20 | def
2 | 30 | def
2 | 40 | ef
I massively oversimplified my example. In addition to selecting the min price and otherAttr from Table B, I also have to select a bunch of other attributes from joins on other tables. Which is why I was thinking the Group By and Min should be a subquery of the join on Table B, as a way to avoid Grouping By all the attributes I am selecting (because the attributes being selected for vary programmatically).
The Actual query looks more like:
SELECT a.name, b.price, b.otherAttr, c.x, c.y, d.e, d.f, g.h....
FROM A a
LEFT Join B b on b.idFromA = 1
LEFT Join C c on something...
LEFT Join D d on something...
LEFT Join G g on something...
WHERE a.id = 1
To get this, you could use GROUP BY in an INNER query:
SELECT gd.name, gd.price,gd.otherAttr, c.x, c.y, d.e, d.f, g.h....
FROM
(SELECT a.id,a.name, MIN(b.price) as price, b.otherAttr
FROM A a
LEFT Join B b on b.idFromA = 1
WHERE a.id = 1
GROUP BY a.id,a.name,b.otherAttr) gd
LEFT Join B b on b.idFromA = 1
LEFT Join C c on something...
LEFT Join D d on something...
LEFT Join G g on something...
Try:-
SELECT a.name, MIN(b.price) minprice, b.otherAttr
FROM A a
LEFT Join B b ON a.Id = b.idFromA
GROUP BY a.name, b.otherAttr
HAVING a.id = 1
You could just do this instead:
SELECT a.name, MIN(b.price), MIN(b.otherAttr)
FROM TableA a
LEFT JOIN TableB b on b.idFromA = a.id
GROUP BY a.name
HAVING a.id = 1;
You need to inner join on price as well in addition to id on the subquery to intersect the right record(s) with the lowest price(s). Then TOP(1) will return only one of those records. You can avoid using TOP(1) if you can expand the conditions and group by fields in the subquery so you schema can assure only a single record is returned for that combination of attributes. Lastly, avoid left joins when intersecting sets.
SELECT TOP(1) p.id, p.price, b.OtherAttr
FROM B as b
INNER JOIN
(SELECT A.id, min(B.price) as price
FROM B
INNER JOIN A on A.id=B.idFromA and A.ID=1
GROUP BY A.id) as p on b.idFromA=p.id and b.price=p.price
I have 2 tables which I'd like to join and..
A:
ID Otherfields..
1 ...
2
3
4
B:
ID aId Otherfields..
1 1 ...
2 1
3 2
4 1
So I'm perfectly capable of joining them by a.Id but how do get I get the count for the matches in Table B, like:
a.id count(b)
1 3
2 1
I figured it must be something with count() over() but cannot recall the exact use.
Thanks!
You can simply do this:
SELECT
A.ID, COUNT(b.ID)
FROM A
INNER JOIN B ON A.Id = b.aID
GROUP BY A.ID
You can have
SELECT A.ID, COUNT(b.ID)
FROM A
LEFT JOIN B ON A.Id = b.aID
GROUP BY A.ID
This will give you all a.IDs that don't exist in b.ID and hence show their count as 0.
E.g.,
ID Count
1 3
2 1
3 0
4 0