combine 2 query statements into one - sql

hi I have 2 sql query and I would like to run it in one query
so to explain about the query the first one to get the most frequent brand names
then the second one to get the most item sold with empty brand name column
now I want to combine both so I can get the list of products where they have empty brand name column but the name of product contains the list of brands I have
here is my 2 query
select brand_name as top_brands
from "catalog-my"."catalog_my_20210425"
where store_merchant_id like '%lazada%' and brand_name in ( 'HP' ,'Acer','VAKIND','Casio','Lenovo','BF1 Soul',
'Sony','Lenovo','Samsung','Bosch','Xiaomi',
'Panasonic','Dell','Rondaful','Toshiba','UCUC',
'zanzea','CAMERON SINO','ZZOOI','Canon',
'Philips','LEGO','Glamorousky','ZeroQiQi','Baosity','Huawei'
,'Alloet','Hontinga','OME','Jotun','Yamaha')
group by brand_name
and the second query
SELECT name
,item_sold_30d
,brand_name
,category_name
,product_url
FROM (
SELECT DISTINCT b.name,b.item_sold_30d , b.brand_name ,b.category_name, a.product_url, ROW_NUMBER() OVER (PARTITION BY b.name,b.item_sold_30d , b.brand_name ,b.category_name ORDER BY a.product_url) as rowId
FROM "dasync"."outputs_lazada_my"a
INNER JOIN "catalog-my"."catalog_my_20210425"b ON b.name = a.name
WHERE b.name like '%'||brand_name||'%' and b.brand_name =''
ORDER BY b.item_sold_30d DESC
) dt
WHERE dt.rowId = 1
limit 10;
please help me to combine these 2

Related

How to include column not included in Group By

I have the table DirectCosts with the following columns:
DetailsID (unique)
InvoiceNumber
ProjectID
PayableID
I need to find the duplicates combinations of payableid and invoicenumber.
How can I adjust the following query so that it accommodates the combination AND displays the list of instead of the count?
SELECT sinvoicenumber, count(*)
FROM exportdirectcostdetails where iprocoreprojectid = 1187294
GROUP BY sinvoicenumber
HAVING COUNT(*) > 2
Is there a way it can display all columns?
Original Question : Why do I get error ed2 should have column name defined
You are having a derived table, so you need to have column names for the derived table.
select ed1.sinvoicenumber,
ed1.ipayableid,
ed2.sinvoicenumber
from ExportDirectCostDetails ed1
inner join
(
SELECT sinvoicenumber, count(sinvoicenumber) AS InvoiceNumberCount
FROM exportdirectcostdetails
where iprocoreprojectid = 1187294
GROUP BY sinvoicenumber
HAVING COUNT(*) > 2
) ed2
on ed1.sinvoicenumber = ed2.sinvoicenumber
Updated Question: How to have all column names
You need to have PARTITION BY clause defined and then apply filter as given below:
SELECT t.* FROM
(SELECT *, count(*) OVER(PARTITION BY payableid,invoiceNumber) AS InvoiceCount
FROM exportdirectcostdetails where iprocoreprojectid = 1187294) as t
WHERE InvoiceCount > 1

Produce one row in an Oracle sql query using group_by

I'm using Oracle 10.g. I have a table, LIB_BOOK, containing a listing of books in a library. There are multiple copies of many of the books. I'd like to produce a report that lists all the books with more than one copy. I've constructed a query that lists the books, but I can't find a way to get only one row for the result.
Select
title
, copy_number
, isbn_10
, category
, book_pk
, max(copy_number)
From LIB_BOOK
Group by
title
, copy_number
, isbn_10
, category
, book_pk
Order by copy_number desc
;
As you can see in the data result below, I get the results for "Conversations with God - Book 1" listed seven times. I'd like that book to be listed only once with a "7" as the copy_number.
I took the first 32 rows of the query result, exported it to Excel and pasted the image below.
How do I construct a query to result in only one row per book, and avoid books with only one copy (copy_number > 1)?
Thanks for looking at this.
Try this
Select
title
, copy_number
, isbn_10
, category
, book_pk
, copy_number
From LIB_BOOK lib
join (select title,max(copy_number) as maxcopynumber
from LIB_BOOK group by title) maxcopy on lib.title = maxcopy.title and lib.copy_number = maxcopy.maxcopynumber
Order by lib.copy_number desc
;
You need to remove copy_number() and book_pk from the group by:
Select title, isbn_10, category,
max(copy_number)
From LIB_BOOK
Group by title, isbn_10, category
Order by max(copy_number) desc;
I'm not sure what you want for book_pk, so I just removed it from the select.
It looks like you only want to list the duplicate books, no matter what category, copy number etc. So group by book (isbn and title) and count, then remove books with less than 2 copies in your HAVING clause:
select
title
, isbn_10
, max(copy_number) as max_copy_number
, count(*) as number_of_copies
from lib_book
group by title, isbn_10
having count(*) > 1
order by count(*) desc;
You can use the unsupported WM_CONCAT to list categories and book pks:
select
title
, isbn_10
, max(copy_number) as max_copy_number
, count(*) as number_of_copies
, wm_concat(distinct category) as categories
, wm_concat(book_pk) as book_pks
...
Note that you are getting getting multiple rows because some of the fields which you are grouping by are different for the same book like copy number and book pk ...
Please try the below query:
SELECT *
FROM (SELECT TITLE,
COPY_NUMBER,
ISBN_10,
CATEGORY,
BOOK_PK,
COPY_NUMBER,
ROW_NUMBER() OVER (PARTITION BY ISBN ORDER BY COPY_NUMBER DESC) RN
FROM LIB_BOOK) X
WHERE RN = 1

SQL Nested Select -Subquery returned more than 1 value-

I have a table Sales with columns SalesID, SalesName, SalesCity, SalesState.
I am trying to come up with a query that only shows salesName where there is one SalesName per SalesCity. So for example, if SaleA is in Houston and SaleB is in Houston, SaleA and SaleB will not be returned.
select
SalesName, SalesCity, SalesState
from
Sales
where
(select count(*) from Sales group by SalesCity) = 1;
I am not entirely sure how to link the inner select back out. I need another column in the nested select to identify the SalesID. I am currently stuck and have made no progress.
You can get the names of cities that have only 1 sale by using GROUP BY and HAVING operators. Then use these results in your where clause:
SELECT SalesName, SalesCity, SalesState
FROM Sales WHERE SalesCity IN
(
SELECT SalesCity
FROM Sales
GROUP BY SalesCity
HAVING COUNT(SalesCity) = 1
)
You can do this without a subquery:
select MIN(SalesName) as SalesName, SalesCity, MIN(SalesState) as SalesState
from Sales
group by SalesCity
having count(*) = 1;
If there is only one row for the city, then the min() will return the value on that row.

Issue selecting Category and SubCategory of an Item while creating one delimited string per row of a table

Some Context: The DB is Oracle. I am trying to create one delimited string per row of a table. The delimited string needs to contain two of the item's categories (if available, there will always be one category at a minimum). There are 3 tables, ITEM, ITEM_CAT and ITEM_ITEM_CAT. The ITEM table holds all the items. The ITEM_CAT table holds all the possible item categories. The ITEM_ITEM_CAT holds all the mappings between the item IDs and the category IDs, a key value table essentially.
I have created the below SQL which is able to get the delimited string for a specific item, but I need a query which can run against the entire table.
SELECT 'ITEM'||'%#'|| outerTable.ITEM_ID ||'%#'||
(SELECT midTable.item_cat_nam
FROM
(SELECT innerTable.item_cat_nam AS item_cat_nam, innerTable.item_id AS item_id, ROWNUM AS rn
FROM
(SELECT ic.ITEM_CAT_NAM AS item_cat_nam, i.ITEM_ID AS item_id
FROM ITEM_CAT ic, ITEM_ITEM_CAT iic, ITEM i
WHERE i.ITEM_ID = iic.ITEM_ID
AND iic.ITEM_CAT_CD = ic.ITEM_CAT_CD
AND 287484 = i.item_id
) innerTable
) midTable
WHERE rn = 1
) ||'%#'||
(SELECT midTable.item_cat_nam
FROM
(SELECT innerTable.item_cat_nam AS item_cat_nam, innerTable.item_id AS item_id, ROWNUM AS rn
FROM
(SELECT ic.ITEM_CAT_NAM AS item_cat_nam, i.ITEM_ID AS item_id
FROM ITEM_CAT ic, ITEM_ITEM_CAT iic, ITEM i
WHERE i.ITEM_ID = iic.ITEM_ID
AND iic.ITEM_CAT_CD = ic.ITEM_CAT_CD
AND 287484 = i.item_id
) innerTable
) midTable
WHERE rn = 2
)
FROM OFR outerTable
WHERE outerTable.ITEM_ID = 287484;
I need to be able to pass the outer table's ITEM_ID down into the last inner join. I could do this when I only need the category (via the below SQL statement, only one inner join needed), but with the introduction of multiple categories; I need rownum (to get multiple categories) which then needs more inner joins and I can't seem to pass the ITEM_ID down more than one inner join, and here lies the problem...
SELECT 'ITEM'||'%#'|| outerTable.OFR_ID ||'%#'||
(SELECT ic.ITEM_CAT_NAM
FROM ITEM_CAT ic, ITEM_ITEM_CAT iic, ITEM i
WHERE i.ITEM_ID = iic.ITEM_ID
AND iic.ITEM_CAT_CD = ic.ITEM_CAT_CD
AND outerTable.OFR_ID = i.item_id
AND rownum = 1
) innerTable
FROM OFR outerTable;
Can anyone help with this?
Thank you in advance for any assitance.
No worries. You need something like this...
SELECT 'ITEM' || '%#' || Item_ID || '%#' || CatName1 || '%#' || CatName2
FROM outerTable
INNER JOIN (
SELECT
Item_ID,
MAX(CASE WHEN rn = 1 THEN Item_Cat_Nam ELSE NULL END) CatName1,
MAX(CASE WHEN rn = 2 THEN Item_Cat_Nam ELSE NULL END) CatName2
FROM (
SELECT
Item_ID,
Item_Cat.Item_Cat_Nam,
ROW_NUMBER() OVER (PARTITION BY Item_ID ORDER BY Item_ID) rn
FROM Item
INNER JOIN Item_Item_Cat USING (Item_ID)
INNER JOIN Item_Cat USING (Item_Cat_Cd)
) GROUP BY Item_ID
) USING (Item_ID)
The innermost query uses the ROW_NUMBER function to assign 1, 2, 3, etc. to every category found for each item. The PARTITION BY restarts the numbering at 1 for each item. The ORDER BY is required so I used Item_ID because hey, why not? If you have a preferred column to order by just use that - it will be used to assign the row numbers. The inner query will output something like this:
Item_ID Item_Cat_Nam rn
------- ------------ --
1 Category aa 1
1 Category xy 2
1 Category ef 3
2 Category xy 1
2 Category ax 2
3 Category ef 1
The query surrounding the innermost query uses MAX to flatten the first two rn values for each Item_ID into a single row. The Item_Cat_Nam for rn=1 goes to the CatName1 column and the Item_Cat_Nam for rn=2 goes to the CatName2 column. When it's fed the results shown above you'll end up with this:
Item_ID CatName1 CatName2
------- ----------- -----------
1 Category aa Category xy (note Category ef is rn=3 so it's ignored)
2 Category xy Category ax
3 Category ef (note only one row for Item_ID 3)
Then the very outer query just concatenates everything.
One other thing: I used the "JOIN ... USING" syntax because in this case it lets you eliminate all of the aliases (innerTable, i, ic, iic, midTable, etc.). That's purely because I'm more comfortable with it so it helped me figure this out a lot quicker. You should feel free to use your own join style - after all you'll be the one stuck maintaining it :)

SQL - passing variable from first select to second select

I have one table things full of items listed by ItemID. Given an ItemID, I need to get the record with the ItemID and all other items with the same name.
In the sample data below, given the ItemID of 1, I need to select all records with the same name (in this case, "poptarts") as ItemID 1, including the record with ItemID 1.
ItemID = 1 name = poptarts
ItemID = 7 name = poptarts
ItemID = 8 name = cheddar
ItemID = 323 name = poptarts
select a.ItemID, a.name from things where a.ItemID = '1'
UNION
select b.ItemID, b.name from things where b.name = a.name
The SQL I've written above however does not pass a.name to the second select. Is there any way to pass the first name value to the second select? I would like for the statement to return itemid = 1 as the first row and 7 and 323 as the other rows.
UNION is only really used to concatenate two distinct sets. Based on your example, you could probably do something like this:
SELECT a.ItemID, a.Name
FROM things a
WHERE name IN (SELECT name FROM things WHERE itemID = 1)
There are lots of ways to write this kind of query and will depend on which flavor of SQL you're using but this should be more or less universal.
select
a.itemID,
a.name
from
things a
where a.name in (
select name
from things b
where b.itemID = '1'
)
SELECT this.name, this.id, that.id
FROM thing this
LEFT JOIN thing that ON that.name=this.name AND that.id <> this.id
WHERE this.id = 1
;
NOTE: this also selects the this-rows that have no twin records; in that case the that.id will be NULL. If you want to suppress the records without twin-records, remove the LEFT.
UPDATE: added the id <> id clause to suppres the obvious match.
If you really only have one table, no need to bring it in twice, UNION, or anything fancy like htat.
SELECT
name
FROM
a --assuming this is your only table
GROUP BY
itemID, name
HAVING
itemID = '1'