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 |
I am using following query to count how many Bill_date each BAN have
select replace(c.usertoken, '-', '') as BAN
, to_char(to_date(bi.name,'YYYY-MM-DD'),'dd-mm-yy') as Billdate_dmy
, (replace(c.usertoken, '-', '') ||':'|| to_char(to_date(bi.name,'YYYY-MM-DD'),'dd-mm-yy')) as BAN_Billdate_dmy
, count(c.usertoken) as Number_Of_Bills
from customer c
, service s
, document d
, bill bi
, batch ba
, billrun br
where c.ID = s.CUSTOMER_SERVICE_ID
and s.ID = d.SERVICE_DOCUMENT_ID
and bi.ID = d.BILL_DOCUMENT_ID
and d.BATCH = ba.ID
and ba.BILLRUN = br.ID
and br.STATUS = 'APPROVED'
and c.brand='rogers'
and d.VERSIONEDCONTENTFOLDER='cbu'
group by c.usertoken, bi.name
order by c.usertoken
Output of the above query
+-----------+----------+--------------------+--------------+--+-------+
| BAN | Bill_date | BAN_Billdate | Count |
+-----------+----------+--------------------+--------------+--+-------+
| 100001247 | 25-09-19 | 100001247:25-09-19 | 1 | | |
| 100001247 | 25-10-19 | 100001247:25-10-19 | 1 | | |
| 100002583 | 15-10-19 | 100002583:15-10-19 | 1 | | |
| 100004753 | 25-09-19 | 100004753:25-09-19 | 1 | | |
| 100004753 | 25-10-19 | 100004753:25-10-19 | 1 | | |
| 100005719 | 25-09-19 | 100005719:25-09-19 | 1 | | |
| 100005719 | 25-10-19 | 100005719:25-10-19 | 1 | | |
| 100006311 | 06-09-19 | 100006311:06-09-19 | 1 | | |
| 100009596 | 25-09-19 | 100009596:25-09-19 | 1 | | |
| 100009596 | 25-10-19 | 100009596:25-10-19 | 1 | | |
+-----------+----------+--------------------+--------------+--+-------+
However I was expecting the following output
+-----------+----------+--------------------+--------------+--+-------+
| BAN | Billdate | BAN_Billdate | | Count |
+-----------+----------+--------------------+--------------+--+-------+
| 100001247 | 25-09-19 | 100001247:25-09-19 | 2 | | |
| 100001247 | 25-10-19 | 100001247:25-10-19 | 2 | | |
| 100002583 | 15-10-19 | 100002583:15-10-19 | 3 | | |
| 100004753 | 25-09-19 | 100004753:25-09-19 | 3 | | |
| 100004753 | 25-10-19 | 100004753:25-10-19 | 3 | | |
| 100005719 | 25-09-19 | 100005719:25-09-19 | 2 | | |
| 100005719 | 25-10-19 | 100005719:25-10-19 | 2 | | |
| 100006311 | 06-09-19 | 100006311:06-09-19 | 1 | | |
| 100009596 | 25-09-19 | 100009596:25-09-19 | 2 | | |
| 100009596 | 25-10-19 | 100009596:25-10-19 | 2 | | |
+-----------+----------+--------------------+--------------+--+-------+
Please advise what changes should I do in the query to have the count column reflecting the expected values.
I don't want to touch your query and the archaic join syntax. Please learn proper SQL grammar with JOIN and ON clauses for joins.
That said, you seem to want a window function to sum the counts:
select sum(count(*)) over (partition by ban, to_date(bi.name, 'YYYY-MM-DD'))
I'm not sure that aggregation is really useful, if you are only getting one row per group. In that case, you might want to remove the group by and use:
select count(*) over (partition by ban, to_date(bi.name, 'YYYY-MM-DD'))
I have table for eg "employee" with just one column "id". Say you have records from 1 through 1000.
Employee
------------
ID
------------
1
2
3
..
..
999
1000
Now I would like to write a query which gives the following results i.e. sort by ascending order and concatenate first 5 to 1 record, second 5 to 2 second, and so on. Any ideas how I can do this?
Here is the output I am looking to have.
1,2,3,4,5
6,7,8,9,10
11,12,13,14,15
...........
...........
996,997,998,999,1000
Use row_number and listagg functions, in this way:
SELECT listagg( id, ',' ) within group( order by group_no, id )
FROM (
select id,
trunc((row_number() over( order by id ) -1) / 5) as group_no
from employee
)
GROUP BY group_no
Working demo: http://sqlfiddle.com/#!4/ef526/10
| LISTAGG(ID,',')WITHINGROUP(ORDERBYGROUP_NO,ID) |
|------------------------------------------------|
| 1,2,3,4,5 |
| 6,7,8,9,10 |
| 11,12,13,14,15 |
| 16,17,18,19,20 |
| 21,22,23,24,25 |
| 26,27,28,29,30 |
| 31,32,33,34,35 |
| 36,37,38,39,40 |
| 41,42,43,44,45 |
| 46,47,48,49,50 |
| 51,52,53,54,55 |
| 56,57,58,59,60 |
| 61,62,63,64,65 |
| 66,67,68,69,70 |
| 71,72,73,74,75 |
| 76,77,78,79,80 |
| 81,82,83,84,85 |
| 86,87,88,89,90 |
| 91,92,93,94,95 |
| 96,97,98,99,100 |
| 101,102,103,104,105 |
| 106,107,108,109,110 |
| 111,112,113,114,115 |
| 116,117,118,119,120 |
| 121,122,123,124,125 |
| 126,127,128,129,130 |
| 131,132,133,134,135 |
| 136,137,138,139,140 |
| 141,142,143,144,145 |
| 146,147,148,149,150 |
| 151,152,153,154,155 |
| 156,157,158,159,160 |
| 161,162,163,164,165 |
| 166,167,168,169,170 |
| 171,172,173,174,175 |
| 176,177,178,179,180 |
| 181,182,183,184,185 |
| 186,187,188,189,190 |
| 191,192,193,194,195 |
| 196,197,198,199,200 |
I created some sample tables and data to try LISTAGG
SELECT SALE_TITLE, addr_id, addr_name, addr_desc
, LISTAGG(SALES_ID, ',')
WITHIN GROUP (ORDER BY SALES_ID)
AS SALES_ID
FROM (select a.addr_id, a.addr_name, a.addr_desc,
b.SALES_ID, b.SALE_TITLE,
ROW_NUMBER () OVER (ORDER BY b.SALES_ID ) rn,
COUNT (*) OVER () cnt
from palm.adrss a, palm.sales b
where a.addr_id = b.addr_id)
GROUP BY SALE_TITLE, addr_id, addr_name, addr_desc;
When I run the above query my result set is following
+-----------------+----------+-----------+--------------+-------------+
| SALE_TITLE | ADDR_ID | ADDR_NAME | ADDR_DESC | SALES_ID |
+-----------------+----------+-----------+--------------+-------------+
| Role | 2 | saty | local test | 14,34 |
| Entitlement | 2 | saty | local test | 22,42 |
| Role | 3 | vasu | portal | 14,34 |
| Entitlement | 3 | vasu | portal | 22,42 |
| Role | 4 | sand | Golden gate | 144,344 |
| Entitlement | 4 | sand | Golden gate | 224,424 |
| Role | 5 | Gou | Data Modeler | 144 |
| Suffix | 5 | Gouri | Data Modeler | 224,424 |
| Entitlement | 5 | Gou | Data Modeler | 344 |
| Role | 6 | Mad | Data Analyst | 144 |
| Entitlement | 6 | Mad | Data Analyst | 224,344,424 |
+-----------------+----------+-----------+--------------+-------------+
Now using this result set I want to write another query to get a result set which looks like below. In this Role, Entitlement, Suffix will be column names and will have sale_id's under them
+---------------+--------------+---------+----------------------+---------+
| ADDR_NAME | ADDR_DESC | Role | Entitlement | Suffix |
+---------------+--------------+---------+----------------------+---------+
| saty | local test | 14,34 | 22,42 | |
| vasu | portal | 14,34 | 22,42 | |
| sand | Golden gate | 144,344 | 224,424 | |
| Gou | Data Modeler | 144 | 344 | 224,424 |
| Mad | Data Analyst | 144 | 224,344,424 | |
+---------------+--------------+---------+----------------------+---------+
Please let me know if this is possible and provide me some inputs
Thanks in advance
I saw you have typo on sample data, if you fix it you will get your desired output.
update Your_Table
set ADDR_NAME='Gou'
where ADDR_NAME='Gouri'
Your query should be:
select t1.ADDR_NAME,t1.ADDR_DESC,
max(case when t1.SALE_TITLE='Role' then t2.SALES_ID end) 'Role',
max(case when t1.SALE_TITLE='Entitlement' then t2.SALES_ID end) 'Entitlement',
max(case when t1.SALE_TITLE='Suffix' then t2.SALES_ID end) 'Suffix'
from Your_Table t1
join Your_Table t2
on t1.ADDR_ID=t2.ADDR_ID and t1.SALE_TITLE=t2.SALE_TITLE
group by t1.ADDR_NAME,t1.ADDR_DESC
order by Role
The database I'm working on is DB2 and I have a problem similar to the following scenario:
Table Structure
-------------------------------
| Teacher Seating Arrangement |
-------------------------------
| PK | seat_argmt_id |
| | teacher_id |
-------------------------------
-----------------------------
| Seating Arrangement |
-----------------------------
|PK FK | seat_argmt_id |
|PK | Row_num |
|PK | seat_num |
|PK | child_name |
-----------------------------
Table Data
------------------------------
| Teacher Seating Arrangement|
------------------------------
| seat_argmt_id | teacher_id |
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 5 | 2 |
------------------------------
---------------------------------------------------
| Seating Arrangement |
---------------------------------------------------
| seat_argmt_id | row_num | seat_num | child_name |
| 1 | 1 | 1 | Abe |
| 1 | 1 | 2 | Bob |
| 1 | 1 | 3 | Cat |
| | | | |
| 2 | 1 | 1 | Abe |
| 2 | 1 | 2 | Bob |
| 2 | 1 | 3 | Cat |
| | | | |
| 3 | 1 | 1 | Abe |
| 3 | 1 | 2 | Cat |
| 3 | 1 | 3 | Bob |
| | | | |
| 4 | 1 | 1 | Abe |
| 4 | 1 | 2 | Bob |
| 4 | 1 | 3 | Cat |
| 4 | 2 | 2 | Dan |
---------------------------------------------------
I want to see where there are duplicate seating arrangements for a teacher. And by duplicates I mean where the row_num, seat_num, and child_name are the same among different seat_argmt_id for one teacher_id. So with the data provided above, only seat id 1 and 2 are what I would want to pull back, as they are duplicates on everything but the seat id. If all the children on the 2nd table are exact (sans the primary & foreign key, which is seat_argmt_id in this case), I want to see that.
My initial thought was to do a count(*) group by row#, seat#, and child. Everything with a count of > 1 would mean it's a dupe and = 1 would mean it's unique. That logic only works if you are comparing single rows though. I need to compare multiple rows. I cannot figure out a way to do it via SQL. The solution I have involves going outside of SQL and works (probably). I'm just wondering if there is a way to do it in DB2.
Does this do what you want?
select d.teacher_id, sa.row_num, sa.seat_num, sa.child_name
from seatingarrangement sa join
data d
on sa.seat_argmt_id = d.seat_argmt_id
group by d.teacher_id, sa.row_num, sa.seat_num, sa.child_name
having count(*) > 1;
EDIT:
If you want to find two arrangements that are the same:
select sa1.seat_argmt_id, sa2.seat_argmt_id
from seatingarrangement sa1 join
seatingarrangement sa2
on sa1.seat_argmt_id < sa2.seat_argmt_id and
sa1.row_num = sa2.row_num and
sa1.seat_num = sa2.seat_num and
sa1.child_name = sa2.child_name
group by sa1.seat_argmt_id, sa2.seat_argmt_id
having count(*) = (select count(*) from seatingarrangement sa where sa.seat_argmt_id = sa1.seat_argmt_id) and
count(*) = (select count(*) from seatingarrangement sa where sa.seat_argmt_id = sa2.seat_argmt_id);
This finds the matches between two arrangements and then verifies that the counts are correct.