I want to combined two SQL queries into one - sql

I have two SQL queries that I would like to combined into one, if its possible. The fist is to get information about a shop order and the second is to get revision information from all previous records with the same shop_order_id.
The first query:
SELECT so.shop_order_id, so.shop_order_suffix, so.status, so.mfg_method, so.description
FROM shop_order so
WHERE so.shop_order_id = 'ZZ1810C'
AND so.shop_order_suffix = '000';`
The second query:
SELECT so.user_att27, so.user_att28
FROM shop_order so
WHERE so.shop_order_id LIKE 'ZZ1810C%'
ORDER BY shop_order_suffix DESC;`
Is it possible to combined them so that they run at one time and if so how would i got about doing it?

I think you need a JOIN :
SELECT so.shop_order_id, so.shop_order_suffix, so.status, so.mfg_method, so.description, so2.user_att27, so2.user_att28
FROM shop_order so
JOIN shop_order so2 ON so2.shop_order_id LIKE 'ZZ1810C%'
WHERE so.shop_order_id = 'ZZ1810C' AND so.shop_order_suffix = '000'
ORDER BY shop_order_suffix DESC;

What do you want the results to be? An example would be helpful.
The following combines the two conditions:
SELECT so.shop_order_id, so.shop_order_suffix, so.status, so.mfg_method,
so.description, so.user_att27, so.user_att28
FROM shop_order so
WHERE so.shop_order_id LIKE 'ZZ1810C%'
ORDER BY shop_order_suffix DESC;
This will list all the rows for the shop order, with the initial information duplicated on each row. The additional fields tell you about the revisions.

You mentioned that the intent of the second query is to get all previous records with the SAME shop_order_id, but the second query filters on shop_order_ids that START WITH the provided text, as specified by the LIKE clause.
If the intent is to include all of these, the two queries are from the same table, so just grab the union of all columns for all such entries. I'd order by shop_order_id so that the one without any additional suffix text shows up first:
SELECT so.shop_order_id, so.shop_order_suffix, so.status, so.mfg_method, so.description, so.user_att27, so.user_attr28 FROM shop_order so WHERE so.shop_order_id LIKE 'ZZ1810C%' AND so.shop_order_suffix='000' ORDER BY so.shop_order_id DESC;

Related

BigQuery Query working with multiple "likes" but not working with "in"

I would like to isolate some emails with specific titles. I can use multiple "like"s connected with an ORs in the where clause. This gives me a number of results. However, if I try to do a ____ in ('____', '____', etc), the code suddenly returns nothing.
This does not work.
select DATE_TRUNC(DATE(send_time,"America/Los_Angeles"), week(monday)) as week,
status,
settings_title,
sum(emails_sent) as emails_sent,
sum(report_summary_opens) as report_summary_opens,
sum(report_summary_unique_opens) as report_summary_unique_opens,
sum(report_summary_subscriber_clicks) as report_summary_subscriber_clicks
from mailchimp.campaigns_view
where status = 'sent'
and settings_title in ('%_LL_%', '%_IC_%', '%_AC_%', '%_CC_%', '%_PC_%')
group by 1,2,3
order by 1 desc
However, this works.
select DATE_TRUNC(DATE(send_time,"America/Los_Angeles"), week(monday)) as week,
status,
settings_title,
sum(emails_sent) as emails_sent,
sum(report_summary_opens) as report_summary_opens,
sum(report_summary_unique_opens) as report_summary_unique_opens,
sum(report_summary_subscriber_clicks) as report_summary_subscriber_clicks
from mailchimp.campaigns_view
where status = 'sent'
and (settings_title like '%_LL_%'
or settings_title like '%_IC_%'
or settings_title like '%_AC_%'
or settings_title like '%_CC_%'
or settings_title like '%_PC_%')
group by 1,2,3
order by 1 desc
I have already tried to include a subquery in my "from" that eliminates all null settings_title. Any ideas why this is not working? Am I missing some small syntax error?
Thanks for the help!
The % symbol will only work with LIKE. For IN it's only equality. Try REGEXP_CONTAINS too.
As in:
SELECT REGEXP_CONTAINS("abcdefg", '(xxx|zzz|yyy|cd)')
Thanks Felipe, very usefull!!!. In my case I used REGEXP_CONTAINS for matching with a multiple patterns added to a table. The select with the column "pattern_str" located in the second position is able to search and find correctly for every portion of the parttern:
WITH CTE_PatternCovid as (
Select STRING_AGG(Pattern,'|') as strPattern from xxxxxxxxx.TEMP.Temp_patternsearch_covid 
)
--this convert the multiple patterns into a single line:
--.*MASK.FFP.|.*MASK.KN.|.*TEST.ANTIG.|.*MASK.QUI.|.*SP.*H.DRO.AL.
--then use in this way:
Select ProductName FROM xxxxxxxxx.TEMP.Table_ProductsName_covid 
where
regexp_contains (upper(ProductName),(SELECT strPattern FROM CTE_PatternCovid ))

SQL Statement to select row where previous row status = 'C' AS400

This is being run on sql for IBMI Series 7
I have a table which stores info about orders. Each row has an order number (ON), part number(PN), and sequence number(SEQ). Each ON will have multiple PN's linked to them and each part number has multiple SEQ Number. Each sequence number represents the order in which to do work on the part. Somewhere else in the system once the part is at a location and ready to be worked on it shows a flag. What I want to do is get a list of orders for a location that have not yet arrived but have been closed out on the previous location( Which means the part is on it's way).
I have a query listed below that I believe should work but I get the following error: "The column qualifier or table t undefined". Where is my issue at?
Select * From (SELECT M2ON as Order__Number , M2SEQ as Sequence__Number,
M2PN as Product__Number,ML2OQ as Order__Quantity
FROM M2P
WHERE M2pN in (select R1PN FROM R1P WHERE (RTWC = '7411') AND (R1SEQ = M2SEQ)
)
AND M2ON IN (SELECT M1ON FROM M1P WHERE ML1RCF = '')
ORDER BY ML2OSM ASC) as T
WHERE
T.Order__Number in (Select t3.m2on from (SELECT *
FROM(Select * from m2p
where m2on = t.Order__Number and m2pn = t.Product__Number
order by m2seq asc fetch first 2 rows only
)as t1 order by m2seq asc fetch first row only
) as t3 where t3.m2stat = 'C')
EDIT- Answer for anyone else with this issue
Clutton's Answer worked with slight modification so thank you to him for the fast response! I had to name my outer table and specify that in the subquery otherwise the as400 would kick back and tell me it couldn't find the columns. I also had to order by the sequence number descending so that I grabbed the highest record that was below the parameter(otherwise for example if my sequence number was 20 it could grab 5 even though 10 was available and should be shown first. Here is the subquery I now use. Please note the actual query names m2p as T1.
IFNULL((
SELECT
M2STAT
FROM
M2P as M2P_1
WHERE
M2ON = T1.M2ON
AND M2SEQ < T1.M2SEQ
AND M2PN IN (select R1PN FROM R1P WHERE (RTWC = #WC) AND (R1SEQ = T1.M2SEQ))
ORDER BY M2SEQ DESC
FETCH FIRST ROW ONLY
), 'NULL') as PRIOR_M2STAT
Just reading your question, it looks like something I do frequently to emulate RPG READPE op codes. Is the key to M2P Order/Seq? If so, here is a basic piece that may help you build out the rest of the query.
I am assuming that you are trying to get the prior record by key using SQL. In RPG this would be like doing a READPE on the key for a file with Order/Seq key.
Here is an example using a subquery to get the status field of the prior record.
SELECT
M2ON, M2PN, M2OQ, M2STAT,
IFNULL((
SELECT
M2STAT
FROM
M2P as M2P_1
WHERE
M2P_1.M2ON = M2ON
AND M2P_1.M2SEQ < M2SEQ
FETCH FIRST ROW ONLY
), '') as PRIOR_M2STAT
FROM
M2P
Note that this wraps the subquery in an IFNULL to handle the case where it is the first sequence number and no prior sequence exists.

Need to find average and number of repetitions of column

I have an SQL sentence :
SELECT application.id,title,url,company.name AS company_name,package_name,ranking,date,platform,country.name AS country_name,collection.name AS collection_name,category.name AS category_name FROM application
JOIN application_history ON application_history.application_id = application.id
JOIN company ON application.company_id = company.id
JOIN country ON application_history.country_id = country.id
JOIN collection ON application_history.collection_id = collection.id
JOIN category ON application_history.category_id = category.id
WHERE application.platform=0
AND country.name ='CZ'
AND collection.name='topfreeapplications'
AND category.name='UTILITIES'
AND application_history.ranking <= 10
AND date::date BETWEEN date (CURRENT_DATE - INTERVAL '1 month') AND CURRENT_DATE
ORDER BY application_history.ranking ASC
It produces this result :
I'd like to add both a column average ranking for a given package, and a column number of appearances, which would count the number a package appears in the list. I'd also like to Group results by package_name, so that I don't have redundancies.
So far, I've tried to add a GROUP BY By clause before the ORDER BY :
GROUP BY package_name
But it returns me an error :
column "application.id" must appear in the GROUP BY clause or be used in an aggregate function
If I add each and every column it asks me for, it doesn't work.
I have also tried to count the number of package names, by adding after the SELECT :
COUNT(package_name) AS count
It produces a similar error.
How could I get the result I'm looking for ? Should I make two queries instead, or is it possible to get everything at once ?
I precise I have looked at other answers on S.O, but none of them tries to make the COUNT on a "produced" column.
Thank you for your help.
Edit :
Here is the result I expected at first :
Although Gordon's advice didn't give me the proper result it put me on the good track, when I read this :
From the docs : "Unlike regular aggregate functions, use of a window function does not cause rows to become grouped into a single output row."
So I came back to using COUNT and AVG alone. My problem was that I wanted to display the ranking column and date to check whether things were right. But putting these column into the Select prevented the GROUP BY to work as expected, as mentioned by Jarlh in the comments.
The working query :
SELECT application.id,title,url,company.name AS company_name,package_name,platform,country.name AS country_name,collection.name AS collection_name,category.name AS category_name,
COUNT(package_name) AS count, AVG(application_history.ranking) AS avg
FROM application
JOIN application_history ON application_history.application_id = application.id
JOIN company ON application.company_id = company.id
JOIN country ON application_history.country_id = country.id
JOIN collection ON application_history.collection_id = collection.id
JOIN category ON application_history.category_id = category.id
WHERE application.platform=0
AND country.name ='CZ'
AND collection.name='topfreeapplications'
AND category.name='UTILITIES'
AND application_history.ranking <= 10
AND date::date BETWEEN date (CURRENT_DATE - INTERVAL '1 month') AND CURRENT_DATE
GROUP BY package_name,application.id,company.name,country.name,collection.name,category.name
ORDER BY count DESC
I think you want window/analytic functions. The following adds two columns, one for the count of rows for each package and the other an average ranking for them:
SELECT application.id, title, url, company.name AS company_name, package_name,
ranking, date, platform, country.name AS country_name,
collection.name AS collection_name, category.name AS category_name,
count(*) over (partition by package_name) as count,
avg(ranking) over (partition by package_name) as avg_package_ranking
FROM application . . .

SQL COUNT FORM JOIN TABLES

I have the following sql command:
SELECT "USERNAME"."TOPICS".VALUE,
"USERNAME"."TOPICS".QID,
"USERNAME"."QUESTION".QRATING
FROM "USERNAME"."TOPICS" JOIN "USERNAME"."QUESTION"
ON "USERNAME"."TOPICS".QID = "USERNAME"."QUESTION".QID
AND "USERNAME"."TOPICS".VALUE = 'kia'
ORDER BY QRATING DESC
It works really well, but I want to count how many element returns. So I tried to use:
SELECT COUNT("USERNAME"."TOPICS".QID)
FROM "USERNAME"."TOPICS" JOIN "USERNAME"."QUESTION"
ON "USERNAME"."TOPICS".QID = "USERNAME"."QUESTION".QID
AND "USERNAME"."TOPICS".VALUE = 'kia'
ORDER BY QRATING DESC
But I get the error :
Column reference 'USERNAME.TOPICS.VALUE' is invalid. When the SELECT
list contains at least one aggregate then all entries must be valid
aggregate expressions.
What is the problem?
Hmmm. The ORDER BY should be getting the error, not the SELECT. However, your query would be much easier to understand using table aliases:
SELECT COUNT(t.QID)
FROM "USERNAME"."TOPICS" t JOIN
"USERNAME"."QUESTION" q
ON t.QID = q.QID AND t.VALUE = 'kia';
If the first query works, I see no reason why this would not (and your original without the ORDER BY should also work).

SQL Subquery of Join - concatenation based index to be filtered by max date

I am relatively new to SQL - having only started using it in the last week. I am having some trouble joining 2 tables together by concatenation based indexes (which I can do but it shows up with several dates) and then filtering it by max date
Please see below for the first version that shows the tables joined together.
There are two tables which I need to join.
INVENTORY_TRANSACTION_HIST2 (the job)
inventory_transaction_hist (further details related to the item specifics)
there are no related between these tables so I have had to build concatenated ones from several fields:
part_no||lot_batch_no||serial_no||location_no
is for relating between the two tables.
order_no||release_no||sequence_no||line_item_no
relates only to the second table and creates the required index for filtering the date
select
to_char(job.dated,'dd/mm/yyyy hh:mm:ss') date_issued,
job.userid,
job.part_no,
job.quantity,
job.lot_batch_no,
job.serial_no,
job.cost,
job.quantity* job.cost total_cost,
job.source note,
hist.dated,
hist.order_no,
hist.release_no,
hist.sequence_no,
hist.line_item_no
from
inventory_transaction_job job
left join inventory_transaction_hist hist
on job.part_no||job.lot_batch_no||job.serial_no||job.location_no = hist.part_no||hist.lot_batch_no||hist.serial_no||hist.location_no
where (job.source like UPPER('%'||'&Job_No'||'%') or job.source like LOWER('%'||'&Job_No'||'%'))
and hist.transaction LIKE '%INM-IN%'
and hist.direction LIKE '+'
order by job.part_no
I need to further split this by the most recent date on the hist. table (as some batch / serial numbers are just shown as '*' so can show several order numbers against each - I want to just show the most recent order for these)
I have tried the below and a few other variations but I can't seem to get it working.
select
to_char(job.dated,'dd/mm/yyyy hh:mm:ss') date_issued,
job.userid user_id,
job.part_no,
job.quantity,
job.lot_batch_no,
job.serial_no,
job.cost,
job.quantity* job.cost total_cost,
job.source note,
hist.dated,
hist.order_no,
hist.release_no,
hist.sequence_no,
hist.line_item_no
from
inventory_transaction_job job
left join inventory_transaction_hist hist
on job.part_no||job.lot_batch_no||job.serial_no||job.location_no = hist.part_no||hist.lot_batch_no||hist.serial_no||hist.location_no
where (job.source like UPPER('%'||'&Job_No'||'%') or job.source like LOWER('%'||'&Job_No'||'%'))
and hist.transaction LIKE '%INM-IN%'
and hist.direction LIKE '+'
and job.order_no||job.sequence_no||job.line_item_no IN
(SELECT
hist2.order_no||hist2.sequence_no||hist2.line_item_no
FROM inventory_transaction_hist hist2
WHERE job.part_no||job.lot_batch_no||job.serial_no||job.location_no LIKE hist2.part_no||hist2.lot_batch_no||hist2.serial_no||hist2.location_no
ORDER BY hist2.Dated DESC LIMIT 1)
Any help will be greatly appreciated.
Thank you so much for your help - really appreciate it!
Managed with a bit of tweaking to get it working as i would like.
If you notice anything that could be changed to improve search performance please let me know!
select
to_char(job.dated,'dd/mm/yyyy hh:mm:ss') date_issued,
job.userid user_id,
job.part_no,
job.quantity,
job.lot_batch_no,
job.serial_no,
job.cost,
job.quantity* job.cost total_cost,
job.source note,
to_char(hist.dated,'dd/mm/yyyy hh:mm:ss') date_PO_received,
hist.order_no,
hist.release_no,
hist.sequence_no,
hist.line_item_no
from
INVENTORY_TRANSACTION_job job
left join (select hist.*, MAX(hist.dated) over (PARTITION by hist.transaction, hist.direction, hist.part_no, hist.serial_no, hist.lot_batch_no order by hist.dated desc) as maxdated
from inventory_transaction_hist hist
) hist
on
job.part_no = hist.part_no and
job.lot_batch_no = hist.lot_batch_no and
job.serial_no = hist.serial_no and
hist.dated = hist.maxdated
where (job.source like UPPER('%'||'&Job_No'||'%') or job.source like LOWER('%'||'&Job_No'||'%'))
and hist.transaction LIKE '%INM-IN%'
and hist.direction = '+'
Thanks again
Jamie
First, as mentioned in a comment, you should do joins on the individual columns connected by "ands" rather than trying to concatenate them together. The concatenation is clever, but it makes it much harder for the query optimizer to do its job, for instance.
I got the idea that you want the most recent date from the history table for different groups. I calculate the max date using an analytic function, and then use that for the comparison.
The final query looks like this:
select to_char(job.dated,'dd/mm/yyyy hh:mm:ss') date_issued, job.userid user_id, job.part_no,
job.quantity, job.lot_batch_no, job.serial_no, job.cost, job.quantity* job.cost total_cost,
job.source note, hist.dated, hist.order_no, hist.release_no, hist.sequence_no, hist.line_item_no
from inventory_transaction_job job left join
(select hist.*,
MAX(dated) over (PARTITION by hist2.part_no, hist2.lot_batch_no, hist2.serial_no, hist2.location_no) as maxdated
from inventory_transaction_hist hist
) hist
on job.part_no = hist.part_no and
job.lot_batch_no = hist.lot_batch_no and
job.serial_no = hist.serial_no and
job.location_no = hist.location_no join
(SELECT hist2.order_no, hist2.lot_batch_no, hist2.serial_no, hist2.location_no, hist2.sequence_no, hist2.line_item_no
FROM inventory_transaction_hist hist2
ORDER BY hist2.Dated DESC
LIMIT 1
)
where (job.source like UPPER('%'||'&Job_No'||'%') or job.source like LOWER('%'||'&Job_No'||'%')) and
hist.transaction LIKE '%INM-IN%' and
hist.direction LIKE '+' and
hist.dated = hist.maxdated