Joining PostgreSQL views with selects - sql

I have a couple of views in PostgreSQL that return tables like these:
tickets_new
| id | queue | owner | subject | status | created |
| -- | ----- | ----- | -------- | ------ | ------------------- |
| 1 | 1 | 123 | Subject1 | new | 2022-08-22 16:57:26 |
| 2 | 1 | 345 | Subject2 | new | 2022-08-22 13:24:09 |
tickets_handled
| id | queue | owner | subject | priority | status | created |
| -- | ----- | ----- | -------- | -------- | ------ | ------------------- |
| 3 | 4 | 234 | Subject3 | 0 | open | 2022-08-09 16:57:26 |
| 6 | 4 | 45 | Subject6 | 0 | open | 2022-08-13 13:24:09 |
tickets_planworks
| id | subject | status | starts | due |
| -- | ---------- | ------ | ------------------- | ------------------- |
| 12 | Planworks1 | open | 2022-08-23 21:01:00 | 2022-08-23 23:00:00 |
| 20 | Planworks2 | open | 2022-08-23 21:01:00 | 2022-08-23 23:00:00 |
Then there's table objectcustomfieldvalues with structure:
objectcustomfieldvalues
| id | customfield | objectid | content |
| -- | ----------- | -------- | -------------------- |
| 1 | 1 | 3 | Ticket3_Client |
| 2 | 5 | 2 | Ticket2_Interaction |
| 3 | 13 | 6 | Ticket6_Detalisation |
objectid links to id in tickets views
For example I try to join objectcustomfieldvalues with tickets_handled view with this query:
SELECT tt.id, tt.queue, tt.owner, tt.subject, tt.status,
tt.created,
cf_client.content AS client,
cf_interaction.content AS interaction,
cf_detalisation.content AS detalisation
FROM tickets_handled tt
LEFT JOIN
(SELECT objectid, content
FROM objectcustomfieldvalues
WHERE objectid IN (SELECT id FROM tickets_handled)
AND customfield = '1') cf_client
ON cf_client.objectid=tt.id
LEFT JOIN
(SELECT objectid, content
FROM objectcustomfieldvalues
WHERE objectid IN (SELECT id FROM tickets_handled)
AND customfield = '5') cf_interaction
ON cf_interaction.objectid=tt.id
LEFT JOIN
(SELECT objectid, content
FROM objectcustomfieldvalues
WHERE objectid IN (SELECT id FROM tickets_handled)
AND customfield = '13') cf_detalisation
ON cf_detalisation.objectid=tt.id
And it results to table:
tickets_handled
| id | queue | owner | subject | priority | status | created | client | interaction | detalisation |
| -- | ----- | ----- | -------- | -------- | ------ | ------------------- | -------------- | ----------- | -------------------- |
| 3 | 4 | 234 | Subject3 | 0 | open | 2022-08-09 16:57:26 | Ticket3_Client | | |
| 6 | 4 | 45 | Subject6 | 0 | open | 2022-08-13 13:24:09 | | | Ticket6_Detalisation |
I want to have a procedure or somewhat where i can send a variable with view name (eg tickets_handled) and return table with fields from that view plus fields from table objectcustomfieldvalues linked to tickets in view.
Now when I write join query I have to mention all the fields for each of my views, also repeat view name in selects and write multiple joins for each customfield joined.

Related

SQL column merge with conditions and without duplicates

Trying to combine 2 tables into 1 results table without having duplicate entries.
Conditions are:
1. For each t1name look for each days in t2date, and if there is 1 in t2update, use that info. If there is no 1, then use the 0 row.
2. If the t1name doesn't exist in t2name, create it with the t1date, and set t2update as 0.
Here the are tables examples:
| t1name | t1date | t1department |
| ------ | ---------- | ------------ |
| name 1 | 2000.01.01 | tlc |
| name 1 | 2000.01.01 | tlc |
| name 2 | 2000.01.04 | non-tlc |
| name 3 | 2000.01.04 | non-tlc |
| name 4 | 2000.01.04 | tlc |
| name 5 | 2000.01.04 | tlc |
| name 6 | 2000.01.04 | tlc |
| name 7 | 2000.01.04 | tlc |
Table 1
| t2name | t2update | t2date |
| ------ | -------- | ------------ |
| name 1 | 1 | 2000.01.01 |
| name 1 | 0 | 2000.01.02 |
| name 1 | 1 | 2000.01.02 |
| name 2 | 1 | 2000.01.04 |
| name 2 | 0 | 2000.01.04 |
| name 2 | 0 | 2000.01.09 |
| name 3 | 0 | 2000.01.09 |
| name 3 | 1 | 2000.01.05 |
| name 4 | 0 | 2000.01.03 |
Table 2
| rname | rupdate | rdate |
| ------ | ------- | ------------ |
| name 1 | 1 | 2000.01.01 |
| name 1 | 1 | 2000.01.02 |
| name 2 | 1 | 2000.01.04 |
| name 3 | 0 | 2000.01.02 |
| name 3 | 1 | 2000.01.05 |
| name 4 | 0 | 2000.01.03 |
| name 5 | 0 | 2000.01.09 |
| name 6 | 0 | 2000.01.09 |
| name 7 | 0 | 2000.01.09 |
Results table
Currently using following:
CREATE OR REPLACE VIEW "rtable" AS
(
SELECT DISTINCT
((CASE WHEN (t2.t2updates) > 0) AND (MAX(t1.t1date))) THEN name
, t1.date
, t1.t1department
, t2.updates
FROM (table1 t1
LEFT JOIN table2 t2 on (t2.t2name = t1.t1name))
GROUP BY
, t1.date
, t1.t1department
, t2.updates
ORDER BY t1.t1name ASC
)
And the results return duplicate values per day. For single t1name and t1date have both entries for 1 and 0. Need the outcome in a specific way so it I can do KPI on the updates of the VMs.
After simplifying the approach, and plenty of trials and error, simple right join did the job
CREATE OR REPLACE VIEW "rtable" AS
(
SELECT
t2.name
, t2.date
, t1.t1department
, t2.updates
FROM
(table1 t1
Right JOIN table2 t2 on (t2.t2name = t1.t1name) AND (t2.date = t1.date)))
)

Inserting set of rows for every ID in another table

this is an initial table (this is just a part of a larger table where Article ID's can vary), database is MS Sql.
-----------------------------------
|ArticleID | GroupID |
-----------------------------------
| 1 | NULL |
-----------------------------------
| 2 | NULL |
-----------------------------------
| 3 | NULL |
-----------------------------------
| 4 | NULL |
-----------------------------------
Set of rows that should be entered for each ArticleID looks something like this:
------------------------
| GroupID |
------------------------
| A |
------------------------
| B |
------------------------
| C |
------------------------
| D |
------------------------
Result table should look something like this:
-----------------------------------
|ArticleID | GroupID |
-----------------------------------
| 1 | NULL |
-----------------------------------
| 1 | A |
-----------------------------------
| 1 | B |
-----------------------------------
| 1 | C |
-----------------------------------
| 1 | D |
-----------------------------------
| 2 | NULL |
-----------------------------------
| 2 | A |
-----------------------------------
| 2 | B |
-----------------------------------
| 2 | C |
-----------------------------------
| 2 | D |
-----------------------------------
| 3 | NULL |
-----------------------------------
| 3 | A |
-----------------------------------
| 3 | B |
-----------------------------------
| 3 | C |
-----------------------------------
| 3 | D |
-----------------------------------
| 4 | NULL |
-----------------------------------
| 4 | A |
-----------------------------------
| 4 | B |
-----------------------------------
| 4 | C |
-----------------------------------
| 4 | D |
-----------------------------------
Any suggestion how to insert it efficiently?
Thanks a lot for you suggestion.
Regards
This is a cross join between two sets.
with a as (
select * from(values (1),(2),(3),(4))v(ArticleId)
), g as (
select * from(values (null),('A'),('B'),('C'),('D'))v(GroupId)
)
select *
from a cross join g;
To insert into the original table you could do:
with g as (select * from(values('A'),('B'),('C'),('D'))v(GroupId))
insert into t
select t.ArticleId, g.GroupId
from t cross join g;
See Example Fiddle

Oracle SQL Query Get Value at Max Date

Data:
| ORIGL_ORDER | ORDER | ITEM | DATE | WHSE | QTY |
| ----------- | ----- | ---- | ---------- | ---- | --- |
| 001 | 107 | 9 | 12/29/2020 | 7 | 6 |
| 001 | 110 | 9 | 12/30/2020 | 1 | 4 |
| 001 | 113 | 9 | 12/30/2020 | 3 | 2 |
| 007 | 211 | 3 | 12/20/2020 | 6 | 1 |
| 007 | 219 | 3 | 12/19/2020 | 5 | 3 |
| 018 | 390 | 8 | 12/25/2020 | 2 | 1 |
Original Desired Result:
| ORIGL_ORDER | ORDER | ITEM | MAX_DATE | WHSE |
| ----------- | ----- | ---- | ---------- | ---- |
| 001 | 113 | 9 | 12/30/2020 | 3 |
| 007 | 211 | 3 | 12/20/2020 | 6 |
| 018 | 390 | 8 | 12/25/2020 | 2 |
Original Question: For each ORIGL_ORDER and ITEM, I would like to get the max(DATE) and the WHSE corresponding to the max(Date). If there are more than one orders with the same max(DATE) then the select the largest ORDER number.
New Desired Result:
| ORIGL_ORDER | ORDER | ITEM | MAX_DATE | WHSE | TOTAL_QTY |
| ----------- | ----- | ---- | ---------- | ---- | --------- |
| 001 | 113 | 9 | 12/30/2020 | 3 | 12 |
| 007 | 211 | 3 | 12/20/2020 | 6 | 4 |
| 018 | 390 | 8 | 12/25/2020 | 2 | 1 |
This answers the original version of the question.
Just use row_number():
select t.*
from (select t.*,
row_number() over (partition by ORIGL_ORDER, item order by date desc, order_number desc) as seqnum
from t
) t
where seqnum = 1;

SQL Query - Add column data from another table adding nulls

I have 2 tables, tableStock and tableParts:
tableStock
+----+----------+-------------+
| ID | Num_Part | Description |
+----+----------+-------------+
| 1 | sr37 | plate |
+----+----------+-------------+
| 2 | sr56 | punch |
+----+----------+-------------+
| 3 | sl30 | crimper |
+----+----------+-------------+
| 4 | mp11 | holder |
+----+----------+-------------+
tableParts
+----+----------+-------+
| ID | Location | Stock |
+----+----------+-------+
| 1 | A | 2 |
+----+----------+-------+
| 3 | B | 5 |
+----+----------+-------+
| 5 | C | 2 |
+----+----------+-------+
| 7 | A | 1 |
+----+----------+-------+
And I just want to do this:
+----+----------+-------------+----------+-------+
| ID | Num_Part | Description | Location | Stock |
+----+----------+-------------+----------+-------+
| 1 | sr37 | plate | A | 2 |
+----+----------+-------------+----------+-------+
| 2 | sr56 | punch | NULL | NULL |
+----+----------+-------------+----------+-------+
| 3 | sl30 | crimper | B | 5 |
+----+----------+-------------+----------+-------+
| 4 | mp11 | holder | NULL | NULL |
+----+----------+-------------+----------+-------+
List ALL the rows of the first table and if the second table has the info, in this case 'location' and 'stock', add to the column, if not, just null.
I have been using inner and left join but some rows of the first table disappear because the lack of data in the second one:
select tableStock.ID, tableStock.Num_Part, tableStock.Description, tableParts.Location, tableParts.Stock from tableStock inner join tableParts on tableStock.ID = tableParts.ID;
What can I do?
You can use left join. Here is the demo.
select
s.ID,
Num_Part,
Description,
Location,
Stock
from Stock s
left join Parts p
on s.ID = p.ID
order by
s.ID
output:
| id | num_part | description | location | stock |
| --- | -------- | ----------- | -------- | ----- |
| 1 | sr37 | plate | A | 2 |
| 2 | sr56 | punch | NULL | NULL |
| 3 | sl30 | crimper | B | 5 |
| 4 | mp11 | holder | NULL | NULL |

sort a table while keeping the hierarchy of rows

I have a table which represents the hierarchy of departments:
+-----------+--------------+--------------+--------------+-----------+-------+
| Top Dept. | 2-tier Dept. | 3-tire Dept. | 4-tier Dept. | name | tier |
+-----------+--------------+--------------+--------------+-----------+-------+
| 00 | | | | abc | 0 |
| | 00-01 | | | bcd | 1 |
| | | 00-01-01 | | cde | 2 |
| | | 00-01-02 | | abc | 2 |
| | 00-02 | | | aef | 1 |
| | | 00-02-01 | | qwe | 2 |
| | | 00-02-03 | | abc | 2 |
| | | | 00-02-03-01 | abc | 3 |
+-----------+--------------+--------------+--------------+-----------+-------+
now I want to sort the rows which are in the same tier by their names while keeping the hierarchy overall, That's what I expect:
+-----------+--------------+--------------+--------------+-----------+-------+
| Top Dept. | 2-tier Dept. | 3-tire Dept. | 4-tier Dept. | name | tier |
+-----------+--------------+--------------+--------------+-----------+-------+
| 00 | | | | abc | 0 |
| | 00-02 | | | aef | 1 |
| | | 00-02-03 | | abc | 2 |
| | | 00-02-01 | | qwe | 2 |
| | 00-01 | | | def | 1 |
| | | 00-01-02 | | abc | 2 |
| | | 00-01-01 | | cde | 2 |
| | | | 00-02-03-01 | abc | 3 |
+-----------+--------------+--------------+--------------+-----------+-------+
the missing data means null, I'm using Oracle DB, can anyone help me?
EDIT: Actually, it's a simple version of this sql, I've tried to add a new column which concats the values of the first four columns and then order by it and by name, but it did't work.
Update: This appears to be working... SQL Fiddle
All that was really needed from my original comment was to amend name to department in that order in both selects. This allows the engine to sort by name first, while maintaining the hierarchy.
WITH cte(Dept, superiorDept, name, depth, sort)AS (
SELECT
Dept,
superiorDept,
name,
0,
name|| dept
FROM hierarchy h
WHERE superiorDept IS NULL
UNION ALL
SELECT
h2.Dept,
h2.superiorDept,
h2.name,
cte.depth + 1,
cte.sort || h2.name ||h2.dept
FROM hierarchy h2
INNER JOIN cte ON h2.superiorDept = cte.Dept
)
SELECT
CASE WHEN depth = 0 THEN Dept END AS 一级部门,
CASE WHEN depth = 1 THEN Dept END AS 二级部门,
CASE WHEN depth = 2 THEN Dept END AS 三级部门,
CASE WHEN depth = 3 THEN Dept END AS 四级部门,
name,
depth,
sort
FROM cte
ORDER BY sort, name