SELECT * and SELECT COUNT(*) in one query - sql

My SQL query looks like this
SELECT *
FROM categories AS c
LEFT JOIN LATERAL (SELECT i.*
FROM influencer_profiles AS i
WHERE c.id = i.category_id
ORDER BY i.updated_at
LIMIT 2) AS i ON 1 = 1
INNER JOIN users AS u ON i.user_id = u.id
But I also want to count each influencer_profile for category to display how many influencer_profiles in each categories. How can I use COUNT(*) with selecting all columns?
SELECT *
FROM categories AS c
LEFT JOIN LATERAL (SELECT COUNT(*)
FROM influencer_profiles AS i
WHERE c.id = i.category_id
ORDER BY i.updated_at
LIMIT 2) AS i ON 1 = 1
INNER JOIN users AS u ON i.user_id = u.id
This code doesn't work.

Perhaps you just want a window function. I note that you are using left join in one place and the inner join is undoing it.
So, I am thinking:
SELECT c.*, i.*, u.*,
COUNT(*) OVER (PARTITION BY c.id) as category_cnt
FROM categories c LEFT JOIN LATERAL
(SELECT i.*
FROM influencer_profiles AS i
WHERE c.id = i.category_id
ORDER BY i.updated_at
LIMIT 2
) i
ON 1=1 LEFT JOIN
users u
ON i.user_id = u.id;

Related

How to replace exist in Hive with two correlated subqueries

I have a query that looks like this
SELECT u.id, COUNT(*)
FROM users u, posts p
WHERE u.id = p.owneruserid
AND EXISTS (SELECT COUNT(*) as num
FROM postlinks pl
WHERE pl.postid = p.id
GROUP BY pl.id
HAVING num > 1) --correlated subquery 1
AND EXISTS (SELECT *
FROM comments c
WHERE c.postid = p.id); --correlated subquery 2
GROUP BY u.id
I researched and read that in Hive IN or EXIST are not supported statements. I read that a workaround for this would be to use a LEFT JOIN. I have tried this but I am having trouble with the GROUP BY u.id. I read that this needs to be paired always with an aggregation function like COUNT() however I'm not sure how I can rewrite this query so as to get it to work. All the other examples I have seen online do not seem to be as complicated as this one.
Like you said, you can convert them to left join or may be left join since they uses exists in both subquery. Simply convert your subqueries to inline view and join them with original tables.
SELECT u.id, COUNT(*)
FROM users u
inner join posts p on u.id = p.owneruserid
left outer join (SELECT COUNT(*) as num, pl.postid postid
FROM postlinks pl
GROUP BY pl.postid
HAVING num > 1) pl ON pl.postid = p.id --correlated subquery 1 with left join
left outer join (SELECT postid FROM comments c GROUP BY postid)c ON c.postid = p.id --correlated subquery 2 with left join
WHERE ( c.postid is not null AND pl.postid is not null) -- this ensure data exists in both subquery
GROUP BY u.id
With left join, there may be chance of duplicates, you can use group by in subqry2 to avoid it.

How do i get the list of people not in an inner join?

I am trying to get the exact list
of people who are not part of an inner list. I am not sure if its another join, a NOT EXISTS or a NOT IN function that i should use:
SELECT *
FROM db.user
WHERE NOT EXISTS (SELECT DISTINCT email, m.id, u.status
FROM db.member m
INNER JOIN db.user u
ON m.id=u.member_id
)
Unfortunately the output is blank when I run this query. Althought about 1 million rows should appear.
You can try the query below, which is including a left outer join instead
select distinct u.*
from db.user u
left outer join db.member m on m.id = u.member_id
where m.id is null
Or if u insist using inner join, then try:
;with cte as (
SELECT DISTINCT m.id,
FROM db.member m
INNER JOIN db.user u
ON m.id=u.member_id
)
select *
from db.users u
where u.member_id not in (select id from cte)
You have used U as an alias but it is not defined. Also, you don't need to JOIN when you using EXISTS(). This is correct usage for EXISTS():
SELECT *
FROM db.user U
WHERE NOT EXISTS (SELECT 1
FROM db.member m
WHERE m.id=u.member_id
)

Re-writing query from in() to joins

Can you assist in re-writing this into joins?
select * from users where users.advised_by in (
select p.id
from advisors p
join advisor_members m on p.id = m.advisor_id
join representatives r on m.user_id=r.user_id
where m.memeber_type='Advisor'
)
This is part of 200+ row query and that in() statement is hard to maintain when there are changes.
you should use a proper on clause
select *
from users
inner join
(
select p.id
from advisors p
join advisor_members m on p.id = m.advisor_id
join representatives r on m.user_id=r.user_id
where m.memeber_type='Advisor'
) t on users.advised_by = t.id
/*Option 1 */
SELECT *
FROM users usr
INNER JOIN
(
SELECT p.id AS advisor_id
FROM advisors p
JOIN advisor_members m
ON p.id = m.advisor_id
JOIN representatives r
ON m.user_id=r.user_id
WHERE m.memeber_type='Advisor' ) T2 usr.advised_by = t2.advisor_id
/*Option2 -- */
SELECT *
FROM users usr
INNER JOIN advisors p
ON usr.advised_by=p.id
JOIN
(
SELECT *
FROM advisor_members
WHERE m.memeber_type='Advisor') m
ON p.id = m.advisor_id
JOIN representatives r
ON m.user_id=r.user_id

how to get the counter column based on another column?

I have a table with the info about buildings, a table about expenses, a table about users and a table that does the billing.
In the billing table, I need to have a counter that counts different users inside a building.
I tried to do this with the ROW_NUMBER() but I can't get the desired result.
This is my query so far:
SELECT r.id, r.building_id AS zID,z.name AS zName,
r.user_id AS kID, k.Name AS kName,
expence_id AS uID,u.name AS uName,u.price AS uPrice,
IIF(u.unique=1,u.price,k.kvadratura * u.price) AS Balance,
r.year,r.month,
ROW_NUMBER() OVER(Partition by r.user_id ORDER BY r.id) AS Counter
FROM Bill r
INNER JOIN Expences u ON r.usluga_id = u.id
INNER JOIN Building z ON r.zgrada_id = z.id
INNER JOIN User k ON r.korisnik_id = k.id
WHERE r.building_id =7
This is my output:
What I would want to get is this:
For every user inside a building, counter+1.
You should use DENSE_RANK instead of ROW_NUMBER.
SELECT
r.id, r.building_id AS zID,z.name AS zName,
r.user_id AS kID, k.Name AS kName,
expence_id AS uID,u.name AS uName,u.price AS uPrice,
IIF(u.unique=1,u.price,k.kvadratura * u.price) AS Balance,
r.year,r.month,
DENSE_RANK() OVER(Partition by r.building_id ORDER BY r.user_id) AS Counter
FROM
Bill r
INNER JOIN Expences u ON r.usluga_id = u.id
INNER JOIN Building z ON r.zgrada_id = z.id
INNER JOIN User k ON r.korisnik_id = k.id
WHERE r.building_id = 7
Try to add expence_id to partition.
SELECT r.id, r.building_id AS zID,z.name AS zName,
r.user_id AS kID, k.Name AS kName,
expence_id AS uID,u.name AS uName,u.price AS uPrice,
IIF(u.unique=1,u.price,k.kvadratura * u.price) AS Balance,
r.year,r.month,
ROW_NUMBER() OVER(Partition by r.user_id, expence_id ORDER BY r.id) AS Counter
FROM Bill r
INNER JOIN Expences u ON r.usluga_id = u.id
INNER JOIN Building z ON r.zgrada_id = z.id
INNER JOIN User k ON r.korisnik_id = k.id
WHERE r.building_id =7

SQL joining 3 tables when 1 table is emty

I am trying to write a query that connects 3 tables.
The first table is info about each festival.
The second table is the number of votes for each festival.
The third table is reviews for each festival.
I want to join all 3 tables so I get all the columns from table1, join table1 with table2 on the festivalid, but I also need to count the number of records in table 3 that apply to each festival.
The first 2 tables give me a result because they both have data in them but table 3 is empty because there are no reviews yet so adding that to my query gives me no results.
SELECT f.*,
v.total,
v.votes,
v.festivalid,
r.reviewcount as count
FROM festivals f
INNER
JOIN vote v
ON f.festivalid = v.festivalid
INNER
JOIN (SELECT festivalid,
count(*) as reviewcount
FROM reviews)
GROUP BY festivalid) as r
on r.festivalid = v.festivalid
LEFT OUTER JOIN
e.g.
SELECT f.*,
v.total,
v.votes,
v.festivalid,
r.reviewcount as count
FROM festivals f
INNER
JOIN vote v
ON f.festivalid = v.festivalid
LEFT OUTER
JOIN (SELECT festivalid,
count(*) as reviewcount
FROM reviews
GROUP BY festivalid) as r
on r.festivalid = v.festivalid
SELECT f.*,
v.total,
v.votes,
v.festivalid,
ifnull(r.reviewcount,0) as count
FROM festivals f
INNER
JOIN vote v
ON f.festivalid = v.festivalid
LEFT OUTER
JOIN (SELECT festivalid,
count(*) as reviewcount
FROM reviews)
GROUP BY festivalid) as r
on r.festivalid = v.festivalid
added ifnull to show reviews as 0 in case there are none.
The second join shouldn't be an inner join.
SELECT f.*,
v.total,
v.votes,
v.festivalid,
r.reviewcount as count
FROM festivals f
INNER
JOIN vote v
ON f.festivalid = v.festivalid
LEFT OUTER
JOIN (SELECT festivalid,
count(*) as reviewcount
FROM reviews
GROUP BY festivalid) as r
on r.festivalid = v.festivalid
Article on outer joins:
http://msdn.microsoft.com/en-us/library/ms187518.aspx
Try using a outer join on your review count table (r)
SELECT f.*,
v.total,
v.votes,
v.festivalid,
r.reviewcount as count
FROM festivals f
INNER
JOIN vote v
ON f.festivalid = v.festivalid
LEFT OUTER
JOIN (SELECT festivalid,
count(*) as reviewcount
FROM reviews)
GROUP BY festivalid) as r
on r.festivalid = v.festivalid