DB2/400 - Create new summary table based on joining header and detail tables - sql

I want to Create new summary table based on joining Order header and detail tables.
I am working with this code so far (not yet working). I suspect I have to define data type for MIN fields.
CREATE TABLE SUMMARY AS (
SELECT ORDHED.ORDERNO, ORDHED.CUSTNO,
COUNT(ORDHED.LINENO) AS LINECNT,
MIN((CCSTCN*1000000)+(CCSTYR*10000)+(CCSTMO*100)+CCSTDA) AS ORD_DATE,
MIN(ORDDET.CURRRENCY) AS CURRENCY
FROM ORDHED JOIN ORDDET
ON (ORDHED.ORDERNO= ORDDET.ORDERNO )
GROUP BY ORDHED.ORDERNO, ORDHED.CUSTNO
ORDER BY ORDHED.ORDERNO, ORDHED.CUSTNO
)
WITH DATA;
Simplified version, as original is 3 pages long.

Related

Create a BigQuery view to get the latest rows from a partitioned (and clustered) table

The issue
I'm trying to create a view to get the latest rows from a partitioned table, filtered on the date partition _LOCALDATETIME and zero or more cluster fields. I can create a view which uses a partition and I can create a view which handles some filters, but I can't work out the syntax to achieve both.
An example query requirement
SELECT fieldA, fieldB, fieldC FROM theView
WHERE date between '2021-01-01' and '2021-12-31' AND
_CLUSTERFIELD1 = 'foo'
GROUPBY _CLUSTERFIELD2
ORDERBY _CLUSTERFIELD3
Table schema
_LOCALDATETIME
_id
_CLUSTERFIELD1
_CLUSTERFIELD2
_CLUSTERFIELD3
_CLUSTERFIELD4
...other fields
Base on what I'm understanding from your case I have come with this approach.
I have created partion table based on _LOCALDATETIME with clustered fields and then the view that returns the data from a defined date scope and the value of the last elements based on _id. So, that will allow me to have a view which have the last items of a partitioned table from a fixed date range.
view
CREATE VIEW `<my-project-id>.<dataset>.<table>` AS
with range_id as (
select MAX(_id) as last_id_partition,_localdatetime as partition_ FROM
`<my-project-id>.<dataset>.<table>` where _localdatetime BETWEEN "2020-01-01" and "2022-01-01" group by _localdatetime)
SELECT s.*
FROM
`<my-project-id>.<dataset>.<table>` s
inner join range_id r on s._id = r.last_id_partition and s._localdatetime = r.partition_
where _localdatetime BETWEEN "2020-01-01" and "2022-01-01"
group by _id,_localdatetime,_name,_location
The view will return the last ids of a partioned clustered table with the clustered fields that are within the view (which is for year 2020 and 2021).
query
select * from `<my-project-id>.<dataset>.<table>`
WHERE _localdatetime between '2021-12-21' and '2021-12-22'
and <clusteredfield> = 'Venezuela'
It will return the records available for that filter as the data its already defined in the view.
What you can't do is to have a view without the partition field as it must exist to query a partitioned table. You can also update use the queries inside a function to further customize your outputs.

in QLIK, how do I add data from table B to table A based on conditions in table A

still not completely understanding how to do certain things in qlik.
I have a table payments, which includes a payment status, and a reference_key
I have a table payment references which has a reference_key and a
reference_number.
payments has like 100 fields in it.
I just want to end up with a field in payments which has the reference number if the status is paid, and is blank if it's not - and I'm finding it oddly hard to do.
in sql it would just be
select
payments.*,
case when status='paid' then reference_number else '' end as reference_number
from
payments
inner join references on payments.reference_key = references.reference_key
but I'm having a real trouble doing this in qlik - what I tried to do is
left join (payments)
load reference_key, reference_number from [references.qvd](qvd)
where status = 'paid';
but that just gives me field "status" is not found - because of course the status isn't in references.
The only thing I can come up with that works is create rename payments to payments_temp, join to references - create another payments_temp_2 table with a calculated field with if() in that one - then create a new payments table from payments_temp_2 which drops the reference_number column and renames calculated_reference_number to reference_number - which ends up about ~350 lines of code.
clearly I'm doing something wrong - but how do I do it - it seems such a simple thing - and such a common problem?
Note - any number of lines of payments, with all difference statuses - could all be joining to the same reference number
Probably not code length efficient as sql code but the principle is the same. What you can do, in advance, is to prepare the new reference_number field (based on the status) in separate table (without loading the full table). Then join to the main table, drop the orignal reference_number and rename the new field to reference_number
// Join both references and payments tables but load only the required fields
// reference_key, reference_number and status
TempTable:
Load
Distinct
reference_key,
reference_number
from
references.qvd (qvd);
inner join (TempTable)
Load
Distinct
status,
reference_key
from
payments.qvd (qvd)
;
// perform the "if" statement calculation
ReferenceNumberStatus:
Load
reference_number,
reference_key,
if(status = 'paid', reference_number, '') as reference_number_status
Resident
TempTable
;
// we dont need this table anymore
Drop Table TempTable;
// load full payments table
// and join the table with the status calculation
Payments:
Load
*
from
payments.qvd (qvd)
;
join (Payments)
Load
reference_number,
reference_number_status
Resident
ReferenceNumberStatus
;
// we dont need this table anymore
Drop Table ReferenceNumberStatus;
// drop the original reference_number
Drop Field reference_number from Payments;
// rename the new reference_number_status field to reference_number
Rename Field reference_number_status to reference_number;

Inserting columns with subquery/join

I am having troubles to insert correct data into my tables. I have tables as below:
Here are tables with data:
• Theatre(Theatre#, Name)
• Trow(TR#, RowName, RowType, Theatre#)
• Tseat(TS#, SeatNo, TR#)
• Season(Season#, SeasonName, Year)
• Production(P#, Season#, Title)
• ProductionRun(P#, Theatre#)
• Performance(Per#, P#, Theatre#,Weekday)
• Client(Client#,name )
• TicketPurchase(Purchase#, Client#, Per#,TotalAmount, TS#)
My tables are for example as below:
• ProductionMy(P#,Title)
Into this table I would like to insert columns P# and Title from table Production and to insert only rows where column Per# from table Performance matches column Per# in table TicketPurchase
Another table for example is :
• TimeID(TimeID,Month,Year,Weekday,SeasonName)
I would need to insert unique instances of time from table Performance and SeasonName from Season table based on criteria if Per# in Performance table and Per# in TicketPurchase table matches. I tried for example below with no success:
insert into time select time_seq.nextval,month,year,weekday,SeasonNAme from
(select distinct
extract(month from pDate) month,
extract(year from pDate) year,
Weekday,
SeasonName
from Performance, Season);
Or another example .I have table:
TRowMY(TR#,RowType)
I would like to insert here data from RowType,TR# columns in RowType table based on the criteria that TS# column in TicketPurchase table matches TS# column in TSeat table.
Or another example, my table:
ClientMy(Client#,Name)
I want to insert columns Client#,Name from column Client only when Client# in Client table matches CLient# in TicketPurchase table.
Basically I need to insert data that has been involved in ticket sales as not all performance, seasons, or productions/clients that are in tables are in the TicketPurchase table.
I really stuck in here, please could you at least help me with some tables, so that I will have idea who to deal with rest, please.
Hope i have explained this well...
Regards,
I believe you are looking for something like this.
INSERT INTO ClientMy(id, name)
SELECT Client#,Name FROM Client AS C1 WHERE Client# IN (SELECT Client# FROM
TicketPurchase WHERE Client# = C1.Client#)
Maybe I am wrong, but I think I didn't fully understood what you wanted.

Merge 2 tables and pull the latest record from them

Say I have two customer tables which have pretty much the same columns. One of them is a temporal one which periodically updates the other one. That is, updates and additions to the records are done to the temporal table only. Say they're names are CUSTOMER, and CUSTOMER_TEMP.
The tables got information like ID, NAME, LAST_NAME, and ADDRESS.
This temporal table has three extra fields, TEMP_ID, RECORD_TYPE, and DATE. The record type is used to record whether there was an addition or an update. So the thing is I need to select the latest record from both tables. That involves several cases
Main table has record, but temporal doesn't -> Select main table record.
Main table has no record, but temporal does -> Select latest temporal table record.
Main table has record and temporal has an add record -> Select temporal table record.
Main table has record and temporal table has update record -> Select temporal table record.
Main table has record and temporal table has add and update record. -> Select temporal table update record.
Main table has record and temporal table has various update records. -> Select latest temporal table update record.
Main table has record and temporal table has add record and various update records. -> Select latest temporal table update record.
Now, I don't know whether this is a good flow or not. I was just told to make the query, so I don't have access to the DB, I believe I could make suggestions though. The thing is My SLQ knowledge is not enough to build this query. I know there's an INNER_JOIN involved, as well as a filter by date, and probably and EXIST, to check whether the record exist or not in the CUSTOMER_TEMP table. But I don't quite know how to build it. I'm working on .Net And SQLServer. Any help on it is quite appreciated.
select m.*, 0 as [rn]
from main m
where not exists (select 1 from temp where temp.id = m.id)
union
select tt.*
from ( select temp.*
, row_number() over (partition by id order by RECORD_TYPE desc, date desc) as rn
from temp
-- join main
-- on temp.ID = main.ID
) tt
where tt.rn = 1
if update does not sort last then need to do a trick like in the answer from Tom H
;WITH CTE_Latest_Temporal AS
(
SELECT
id,
name,
..., -- Put the rest of your columns here
ROW_NUMBER OVER (PARTITION BY id
ORDER BY
CASE record_type
WHEN 'Update' THEN 0
ELSE 1
END, date DESC) AS row_num
FROM
Customer_Temp
)
SELECT
M.id,
CASE WHEN T.id IS NOT NULL THEN T.name ELSE M.name END AS name,
... -- Similar CASE statements for the rest of your columns
FROM
Customer M
LEFT OUTER JOIN CTE_Latest_Temporal T ON
T.id = M.id AND
T.row_num = 1
The CASE statements can be replaced by a simple COALESCE(T.column, M.column) for any columns that cannot be NULL. I had to use the CASE to cover situations where the row might exist in the temp table but the column might be NULL in the temp table, but have a value in the main table.

Insert output IDs into another table

I have a status table, and another table containing additional data. My object IDs are the PK in the status table, so I need to insert those into the additional data table for each new row.
I need to insert a new row into my statusTable for each new listing, containing just constants.
declare #temp TABLE(listingID int)
insert into statusTable(status, date)
output Inserted.listingID into #temp
select 1, getdate()
from anotherImportedTable
This gets me enough new listing IDs to use.
I now need to insert the actual listing data into another table, and map each row to one of those listingIDs -
insert into listingExtraData(listingID, data)
select t.listingID, a.data
from #temp t, anotherImportedTable a
Now this obviously doesn't work, because otherDataTable and the IDs in #temp are unrelated... so I get far too many rows inserted.
How can I insert each row from anotherImportedTable into listingExtraData along with a unique newly created listingID? could I possibly trigger some more sql at the point I do the output in the first block of sql?
edit: thanks for the input so far, here's what the tables look like:
anotherImportedTable:
data
statusTable:
listingID (pk), status, date
listingExtraData:
data, listingID
You see that I only want to create one entry into statusTable per row in anotherImportedTable, then put one listingID with a row from anotherImportedTable into listingExtraData... I'm thinking that I might have to resort to a cursor perhaps?
Ok, here's how you can do it (if I'm right about what you actually want to do):
insert into listingExtraData(listingID, data)
select q1.listingID, q2.data
from
(select ListingID, ROW_NUMBER() OVER (order by ListingID) as rn from #temp t) as q1
inner join (select data, ROW_NUMBER() over (order by data) as rn from anotherImportedTable) q2 on q1.rn = q2.rn
In case you matching logic differs you will need to change sorting of anotherImportedTable. In case your match order can not be achieved by ordering anotherImportTable [in one way or another] then you're out of luck.