recursive query in postgresql - sql

I have the following table:
and I have the following query:
WITH RECURSIVE users_r AS (
SELECT user_id, parent_id, 0 as level
FROM users
WHERE parent_id is null
UNION ALL
SELECT u.user_id, u.parent_id, u.level + 1
FROM users u
INNER JOIN users_r
ON (u.parent_id = users_r.user_id)
)
SELECT * FROM users_r LIMIT 1000
I want to fill "level" column with depending on the count of ancestors. But my code isn't working. It fills rows only where parent_id is null.

It is a simple typo.
The recursive SELECT, immediately after the UNION ALL should not read
SELECT u.user_id, u.parent_id, u.level + 1
but
SELECT u.user_id, u.parent_id, users_r.level + 1
You would have noticed right away if you didn't have a level column in users.

Related

How do i get all the values from 2 tables without doing a Cross Join

I have 2 tables with the following Schema
First ( id, user_id, user_agent, referrer, browser, device_type, IP)
Second ( id, user_id, name, properties)
Table First has a total of 512 entries for user_id 1. Table Second has total of 100 entries for user_id 1. Both tables track different User Activities, so anytime I try to join Table Second on First for user_id 1.
SELECT COUNT(*)
FROM first f
JOIN second AS s ON s.user_id = f.user_id
WHERE f.user_id = 1
I get a total of 51,200 returned rows. Definitely, a Cross Join (first * second) is being done. Is there no way I can get a less enormous returned result? perhaps first + second resul
I think you can use UNION ALL operator.
The SQL UNION ALL operator is used to combine the result sets of 2 or more SELECT statements. It does not remove duplicate rows between the various
Each SELECT statement within the UNION ALL must have the same number of fields in the result sets with similar data types. So that you need create same column's with null as ""
Or you can try use UNION
UNION removes duplicate rows.
UNION ALL does not remove duplicate rows.
select *
from(
SELECT id, user_id, user_agent, referrer, browser, device_type, IP, null as "name",
null as "properties"
FROM first f
UNION ALL
SELECT id, user_id, null as "user_agent", null as "referrer", null as "browser",
null as "device_type", null as "IP", name, properties
FROM second s) x
Where user_id = 1
use Left join and use the foreign key to query the two tables

SQL Recursive query over same table

I am new in SQL and I am trying to do a recursive query over the same table to find the brokers of the "master brokers"
I have a table that looks like this (it can grow to any amount of rows and deepness)
So I need a result like this:
master_id => broker_id
I have checked about how to do it and I got:
WITH admin_has_master_brokers
AS (
SELECT DISTINCT master_broker_id, admin_id
FROM admin_has_master_brokers
UNION ALL
/*I DO NOT KNOW HOW TO DO THIS SECTION*/
SELECT
master_broker_id, admin_id
FROM admin_has_master_brokers
)
SELECT
*
FROM
admin_has_master_brokers
ORDER BY master_broker_id ASC
But I can not understand how to do the recursive part to only get the results I need because I am getting this:
Any idea?
Povided original table is Mytable the query lists all desendants of every master_broker_id.
WITH RECURSIVE admin_has_master_brokers
AS (
SELECT DISTINCT master_broker_id master, master_broker_id, admin_id
FROM mytable
UNION ALL
SELECT a.master,
m.master_broker_id, m.admin_id
FROM admin_has_master_brokers a
JOIN mytable m ON m.master_broker_id = a.admin_id
)
SELECT DISTINCT master, admin_id
FROM
admin_has_master_brokers
ORDER BY master, admin_id

Get result from Multiple Select statement on a single Query

I'm trying to create a stored procedure that will display the result of users managed by a manager. I have tried to use CTE but still was unsuccessful.
What I want,
The first query to select the row whose user name = #name
Second query: return users that are managed by (first query ManagerId)
Third query: return all users that are managed by each (second query ManagerId)
This is the structure of the data:
SQL query:
WITH EmployeeCTE AS
(
(SELECT UserId, Email, ManagerId, Name
FROM Table1
WHERE DisplayName LIKE '%Paul%') tbl1
(SELECT UserId, Email, ManagerId, Name
FROM Table1
WHERE ManagerId = tbl1.UserId) tbl2
(SELECT UserId, Email, ManagerId, Name
FROM Table1
WHERE ManagerId = tbl1.UserId) tbl3
)
--Lastly
SELECT *
FROM EmployeeCTE
Please help anyone.
You just simply need a proper recursive CTE - something like this:
WITH EmployeeCTE AS
(
-- "anchor" for the query
SELECT
UserId, Email, ManagerId, Name,
[Level] = 1
FROM
dbo.Table1
WHERE
Name LIKE '%Paul%'
-- I would personally probably use this condition instead
-- ManagerId IS NULL
UNION ALL
-- recursive part
SELECT
t1.UserId, t1.Email, t1.ManagerId, t1.Name,
e.[Level] + 1
FROM
dbo.Table1 t1
INNER JOIN
EmployeeCTE e ON t1.ManagerId = e.UserId
)
SELECT *
FROM EmployeeCTE
This selects the "anchor" row (or rows), and then "recurses" the manager/employee relationship based on Employee.ManagerId = Manager.UserId. I've also added the Level column so you see on which level (of the hierarchy) each entry is located - the "anchor" will be level 1, each further level down is incremented by 1.
PS: if you need to limit the returned data set to the root level + max. of 2 levels down, you can use the Level column to do so in your final SELECT that selects from the CTE:
WITH EmployeeCTE AS
(
--- as above
)
SELECT *
FROM EmployeeCTE
WHERE [Level] <= 3 -- select root level (1) and max. of 2 levels down

Using Google BigQuery's Comma as UNION ALL with IN clause

I am attempting to perform the following query:
SELECT
author, link_id, COUNT(link_id) as cnt
FROM
[fh-bigquery:reddit_comments.2015_12],
[fh-bigquery:reddit_comments.2015_11]
WHERE link_id IN (
SELECT posts.name
FROM [fh-bigquery:reddit_posts.full_corpus_201512] AS posts
WHERE posts.subreddit = 'politics'
ORDER BY posts.created_utc DESC
LIMIT 300
)
GROUP BY author, link_id
ORDER BY author
I receive this error message upon execution: JOIN (including semi-join) and UNION ALL (comma, date range) may not be combined in a single SELECT statement. Either move the UNION ALL to an inner query or the JOIN to an outer query.
Removing one of the comments tables works fine however I can't seem to figure out how BigQuery's Comma as UNION ALL works. I've attempted to move the union to an inner query but I still get the same error.
The error was in my misunderstanding of move the UNION ALL to an inner query. The resolve the error, I had to put the two tables in a basic select * from .... The working query is as follows:
SELECT
author, link_id, COUNT(link_id) as cnt
FROM (
SELECT *
FROM
[fh-bigquery:reddit_comments.2015_12],
[fh-bigquery:reddit_comments.2015_11]
)
WHERE link_id IN (
SELECT posts.name
FROM [fh-bigquery:reddit_posts.full_corpus_201512] AS posts
WHERE posts.subreddit = 'politics'
ORDER BY posts.created_utc DESC
LIMIT 300
)
GROUP BY author, link_id
ORDER BY author

Selecting TOP 1 Columns where duplicate exists and selecting all where no duplicate exists

Given the list of Names, Accounts and Positions I am trying to:
Select the 1st position where there are more than 1 records with the same Name and Account
If there is only 1 record with the Name and Account, then select details.
My current query looks like the following:
SELECT *
FROM CTE cte1
JOIN
(
SELECT Name, OppName FROM CTE GROUP BY Name, OppName HAVING COUNT(Name)>1
) as cte2
on cte2.Name = cte1.Name and cte2.OppName = cte1.OppName
ORDER BY cte1.OppName, cte1.Name
I have not posted the rest of the CTE query as it is way to long.
However, this is only providing me with the results where the Name and Accounts are the same and the Positions are different.
I.E. If Oera worked at Christie's as a Sales Analyst and a Developer It would only Select the record where Oera worked at Christie's as a Developer.
How do I modify this query accordingly?
Are you looking for something like this?
SELECT *
FROM CTE AS cte1
JOIN
(
SELECT Name, OppName,COUNT(Name) PARTITION BY (Name,OppName) cnt
FROM CTE
) AS cte2
ON cte2.Name = cte1.Name and cte2.OppName = cte1.OppName
WHERE cnt > 1
ORDER BY cte1.OppName, cte1.Name