I have SQL Server 2008 R2.
My source table looks like this:
EmpID Name GroupID
-------------------------
1-KFX xxx 7-ZQMN
7-ZQMN yyy null
AXM-4 zzz 1-KFX
7-ZQOP JJJ QRS-0
QRS-0 kkk null
and so on....
I need to traverse through table to get Top GroupID (Top in the hierarchy) for each EmpID until GroupID is null, and populate EmpID if GroupID is null
I am trying to write a query to achieve results like below, any help is appreciated.
EmpID Name TopGroupID
------------------------
1-KFX xxx 7-ZQMN
7-ZQMN yyy 7-ZQMN
AXM-4 zzz 7-ZQMN
7-ZQOP JJJ QRS-0
QRS-0 kkk QRS-0
This hierarchy problem is solved by using a recursive CTE to find the root node.
CREATE TABLE #tt(EmpID VARCHAR(128) NOT NULL PRIMARY KEY,Name VARCHAR(128),GroupID VARCHAR(128));
INSERT INTO #tt(EmpID,Name,GroupID)VALUES
('1-KFX','xxx','7-ZQMN'),
('7-ZQMN','yyy',null),
('AXM-4','zzz','1-KFX'),
('7-ZQOP','JJJ','QRS-0'),
('QRS-0','kkk',null);
;WITH cte_tr AS (
SELECT EmpId, GroupID, depth=0
FROM #tt
UNION ALL -- what follows is the recursion in the CTE to find the parent, keeping track of depth
SELECT cte_tr.EmpID, GroupId=t.GroupID, depth=cte_tr.depth+1
FROM cte_tr
INNER JOIN #tt AS t ON
t.EmpID=cte_tr.GroupID
WHERE t.GroupID IS NOT NULL
),
cte_depth AS ( -- select the maximum depth for a starting node
SELECT EmpID, max_depth=MAX(depth)
FROM cte_tr
GROUP BY EmpID
)
SELECT cte_depth.EmpID, TopGroupId=ISNULL(cte_tr.GroupID,cte_tr.EmpID)
FROM cte_depth
INNER JOIN cte_tr ON -- select the nodes at the maximum depth
cte_tr.EmpID=cte_depth.EmpID AND
cte_tr.depth=cte_depth.max_depth
ORDER BY cte_tr.EmpID;
DROP TABLE #tt;
Result:
+--------+------------+
| EmpID | TopGroupId |
+--------+------------+
| 1-KFX | 7-ZQMN |
| 7-ZQMN | 7-ZQMN |
| 7-ZQOP | QRS-0 |
| AXM-4 | 7-ZQMN |
| QRS-0 | QRS-0 |
+--------+------------+
Try this...
select
empid,
name
isnull(max(GroupID),empid) 'TopGroupId'
from tablename
group by
empid,name
order by empid
Related
I have multiple tables with different column names like below,
customer table:
c_id,
customer_name,
phone_number,
postal_code
Employee Table: Employee_name, e_id, mobile_no,zip_code
student Table: s_id, student_name, post_code
I need to create view to combine those tables like below
User Table: userId (c_id, e_id, s_id), userName (all name columns), zip_code, contact
Sample Data
Customer Table:
| c_id | Company_Name | Phone |
|----------------------------------|
| 1 | Company 1 | *******|
|----------------------------------|
Employee Table:
| e_id | Employee_Name | Mobile |
|----------------------------------|
| 1 | employee 1 | *******|
|----------------------------------|
Expected View:
| userId | user_Name | contact |
|-------------------------------------|
| c_1 | Company 1 | ******* |
|-------------------------------------|
| e_1 | employee 1 | ******* |
|-------------------------------------|
how to create the view please help me, Thanks in advance
just use Union or Union All depending on duplicate values. based on data
CREATE VIEW view_name
AS
SELECT concat('c_',c_id) AS userId,
company_name AS user_Name,
phone AS contact
FROM customer
UNION
SELECT concat('e_',e_id),
employee_name,
mobile
FROM employee
dbfiddle
based on tables
CREATE VIEW view_name
AS
SELECT c_id AS userId,
customer_name AS userName,
postal_code AS zip_code,
phone_number AS contact
FROM customer
UNION
SELECT e_id,
employee_name,
zip_code,
mobile_no
FROM employee
UNION
SELECT s_id,
student_name,
post_code,
NULL
FROM student
I want to create one RECURSIVE query on a single table in Postgres, which is basically base on Parent and child.
Here is the demo table employee with data
id parentid managerid status
------------------------------------
3741 [null] 1709 7
3742 3741 1709 12
3749 3742 1709 12
3900 3749 1709 4
1) If Status = 12 then the result will be, the data which has status = 12 and all the parents of that particular node.
The expected result will be :
id parentid managerid status
--------------------------------------
3741 [null] 1709 7
3742 3741 1709 12
3749 3742 1709 12
For that I have tried the query which is given below is working fine and giving proper result, even if I change the status value than also its working fine.
WITH RECURSIVE nodes AS (
SELECT s1.id, case when s1.parentid=s1.id then null else s1.parentid end parentid,s1.managerid, s1.status
FROM employees s1 WHERE id IN
(SELECT employees.id FROM employees WHERE
"employees"."status" = 12 AND "employees"."managerid" = 1709)
UNION ALL
SELECT s2.id, case when s2.parentid=s2.id then null else s2.parentid end parentid,s2.managerid, s2.status
FROM employees s2 JOIN nodes ON s2.id = nodes.parentid
)
SELECT distinct nodes.id, nodes.parentid, nodes.managerid, nodes.status
FROM nodes ORDER BY nodes.id ASC NULLS FIRST;
2) If Status != 12 then the result will be, only all the parents of that particular node.
The expected result will be :
id parentid managerid status
--------------------------------------
3741 [null] 1709 7
I want the query for status not equal some value.
WITH RECURSIVE cte AS (
SELECT * FROM tablename
WHERE status != 12
UNION
SELECT t.*
FROM tablename t INNER JOIN cte c
ON c.parentid = t.id
)
SELECT DISTINCT * FROM cte;
For more refer the Demo: demo
This is a very simple solution but I think it should work for smaller sets of data
SELECT * FROM employee
WHERE
status=12
OR id IN (
SELECT DISTINCT parentId FROM employee WHERE status=12
)
`
With this recursive CTE:
with recursive cte as (
select * from tablename
where status = 12
union all
select t.*
from tablename t inner join cte c
on c.parentid = t.id
)
select distinct * from cte;
See the demo.
Results:
| id | parentid | managerid | status |
| ---- | -------- | --------- | ------ |
| 3741 | | 1709 | 7 |
| 3742 | 3741 | 1709 | 12 |
| 3749 | 3742 | 1709 | 12 |
WITH RECURSIVE CTE AS
(
SELECT *
FROM tablename
WHERE status = 12
UNION
SELECT t.*
FROM tablename t
INNER JOIN cte c ON c.Id = t.parentid
)
SELECT t.*
FROM tablename t
LEFT JOIN cte c on t.id=c.id
WHERE c.id IS NULL
ORDER BY id ASC NULLS FIRST;
I'm Nubie.
I want to create a postgresql table by drawing data from several tables
Table1
| partner_id | **project_id** | partner_fund | partner_date |
| 12345 | 099 | 12345.70 | 2003-02-02 |
Table2
| partner_id | partner_name
| 12345 | monster.inc
Table3
| **package_id** | **project_id** |
| 099a | 099 |
Table4
| **package_id** | project_name
| 099a | kill some one
*package_id is corresponding to project_id
I want to make a table like this :
| (if)partner_id | (get)partner_name | (if)project_id (corresponding to package_id)| (get)project_name | partner_fund | partner_date
So, if first row shows partner_id, next column shows partner_name, etc. Please help. Thanks.
You can create a new table from a SELECT query using CREATE TABLE ... AS syntax:
CREATE TABLE new_table AS
SELECT
table1.partner_id,
table2.partner_name,
table3.project_id,
table3.project_name,
table1.partner_fund
FROM table1
INNER JOIN table2 ON (table1.partner_id = table2.partner_id)
INNER JOIN table3 ON (table1.project_id = table3.project_id)
;
...and then you can also add a primary key to the new table, e.g.:
ALTER TABLE new_table ADD PRIMARY KEY (partner_id, project_id);
Query after updated question:
CREATE TABLE new_table AS
SELECT
table1.partner_id,
table2.partner_name,
table1.project_id,
table4.project_name,
table1.partner_fund,
table1.partner_date
FROM table1
INNER JOIN table2 ON (table1.partner_id = table2.partner_id)
INNER JOIN table3 ON (table1.project_id = table3.project_id)
INNER JOIN table4 ON (table3.package_id = table4.package_id)
;
I have 2 tables that I need to join based on distinct rid while replacing the column value with having different values in multiple rows. Better explained with an example set below.
CREATE TABLE usr (rid INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(12) NOT NULL,
email VARCHAR(20) NOT NULL);
CREATE TABLE usr_loc
(rid INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
code CHAR NOT NULL PRIMARY KEY,
loc_id INT NOT NULL PRIMARY KEY);
INSERT INTO usr VALUES
(1,'John','john#product'),
(2,'Linda','linda#product'),
(3,'Greg','greg#product'),
(4,'Kate','kate#product'),
(5,'Johny','johny#product'),
(6,'Mary','mary#test');
INSERT INTO usr_loc VALUES
(1,'A',4532),
(1,'I',4538),
(1,'I',4545),
(2,'I',3123),
(3,'A',4512),
(3,'A',4527),
(4,'I',4567),
(4,'A',4565),
(5,'I',4512),
(6,'I',4567);
(6,'I',4569);
Required Result Set
+-----+-------+------+-----------------+
| rid | name | Code | email |
+-----+-------+------+-----------------+
| 1 | John | B | 'john#product' |
| 2 | Linda | I | 'linda#product' |
| 3 | Greg | A | 'greg#product' |
| 4 | Kate | B | 'kate#product' |
| 5 | Johny | I | 'johny#product' |
| 6 | Mary | I | 'mary#test' |
+-----+-------+------+-----------------+
I have tried some queries to join and some to count but lost with the one which exactly satisfies the whole scenario.
The query I came up with is
SELECT distinct(a.rid)as rid, a.name, a.email, 'B' as code
FROM usr
JOIN usr_loc b ON a.rid=b.rid
WHERE a.rid IN (SELECT rid FROM usr_loc GROUP BY rid HAVING COUNT(*) > 1);`
You need to group by the users and count how many occurrences you have in usr_loc. If more than a single one, then replace the code by B. See below:
select
rid,
name,
case when cnt > 1 then 'B' else min_code end as code,
email
from (
select u.rid, u.name, u.email, min(l.code) as min_code, count(*) as cnt
from usr u
join usr_loc l on l.rid = u.rid
group by u.rid, u.name, u.email
) x;
Seems to me that you are using MySQL, rather than IBM DB2. Is that so?
I am new to postgresssql.
I have two table like this
Table A
id |value | type1 | type2 | type3
bigint |text | bigint | bigint | bigint
Table B
Id | description
bigint | text
Table A's type1,type2,type3 is the ids of Table B but not foreign key constraint.
I have to retrieve like this
Select a.id,
a.value,
b.description1(as of a.type1),
b.description1(as of a.type1),
b.description1(as of a.type1)
If you have to many columns you should consider change your db design
TableA
id | value
1 | <something>
2 | <something>
TableAType
id | TableA.id | type_id | typeValue
1 | 1 | type1 | bigint
2 | 1 | type2 | bigint
3 | 1 | type3 | bigint
.....
4 | 1 | typeN | bigint
TableB (type_description)
Id | description
bigint | text
Then your query become more simple and isn't affected when you add/remove types.
SELECT TB.Description, TT.TypeValue
FROM TableAType TT
JOIN TableB TB
ON TT.Type_id = TB.id
Then you can use a PIVOT to get the tabular data. Again the advantage is you can delete remove types, and your query doesnt change, only need update the types tables.
You should (LEFT) JOIN tableB 3 times, and use a different alias for each one.
select id, value,
type1, t1.description descri1,
type2, t2.description descri2,
type3, t3.description descri3
from tableA ta
left join tableB t1
on ta.type1 = t1.id
left join tableB t2
on ta.type2 = t2.id
left join tableB t3
on ta.type3 = t3.id;