code Attribute1(String)
A C
B D
C Empty
D Empty
how to get the pk's of all A,B,C,D
Note: Using the string value C,D I want to fetch pk of product C,D along with A,B using Flexible search query
Details :
I Have list a of product's.
Inside each of these products there is an attribute called "X" which contains product ID code of type string.
Note : "Product ID Code" means "Product ID" of another product inside the list of products.
Now i want to get pk's of products based upon the Product ID Codes?
I don't understand it fully, but you can try something like this
select {p1.pk},{p2.pk} from {product as p1},{product as p2} WHERE {p1.Attribute1} = {p2.code}
you can add filter to it
AND {p1.Attribute1} in ('C','D')
Using UNION
SELECT uniontable.PK FROM
(
{{
SELECT {p1:PK} AS PK FROM {Product AS p1},{Product AS p2}
WHERE {p1.code} = {p2.Attribute1}
}}
UNION ALL
{{
SELECT {p:PK} AS PK FROM {Product AS p}
WHERE {p1.Attribute1} is not empty
}}
) uniontable
With filter
SELECT uniontable.PK FROM
(
{{
SELECT {p1:PK} AS PK FROM {Product AS p1},{Product AS p2}
WHERE {p1.code} = {p2.Attribute1} AND {p2.Attribute1} in ('C','D')
}}
UNION ALL
{{
SELECT {p:PK} AS PK FROM {Product AS p}
WHERE {p.Attribute1} in ('C','D')
}}
) uniontable
Related
I have a long and wide list, the following table is just an example. Table structure might look a bit horrible using SQL, but I was wondering whether there's a way to extract IDs' price using CASE expression without typing column names in order to match in the expression
IDs
A_Price
B_Price
C_Price
...
A
23
...
B
65
82
...
C
...
A
10
...
..
...
...
...
...
Table I want to achieve:
IDs
price
A
23;10
B
65
C
82
..
...
I tried:
SELECT IDs, string_agg(CASE IDs WHEN 'A' THEN A_Price
WHEN 'B' THEN B_Price
WHEN 'C' THEN C_Price
end::text, ';') as price
FROM table
GROUP BY IDs
ORDER BY IDs
To avoid typing A, B, A_Price, B_Price etc, I tried to format their names and call them from a subquery, but it seems that SQL cannot recognise them as columns and cannot call the corresponding values.
WITH CTE AS (
SELECT IDs, IDs||'_Price' as t FROM ID_list
)
SELECT IDs, string_agg(CASE IDs WHEN CTE.IDs THEN CTE.t
end::text, ';') as price
FROM table
LEFT JOIN CTE cte.IDs=table.IDs
GROUP BY IDs
ORDER BY IDs
You can use a document type like json or hstore as stepping stone:
Basic query:
SELECT t.ids
, to_json(t.*) ->> (t.ids || '_price') AS price
FROM tbl t;
to_json() converts the whole row to a JSON object, which you can then pick a (dynamically concatenated) key from.
Your aggregation:
SELECT t.ids
, string_agg(to_json(t.*) ->> (t.ids || '_price'), ';') AS prices
FROM tbl t
GROUP BY 1
ORDER BY 1;
Converting the whole (big?) row adds some overhead, but you have to read the whole table for your query anyway.
A union would be one approach here:
SELECT IDs, A_Price FROM yourTable WHERE A_Price IS NOT NULL
UNION ALL
SELECT IDs, B_Price FROM yourTable WHERE B_Price IS NOT NULL
UNION ALL
SELECT IDs, C_Price FROM yourTable WHERE C_Price IS NOT NULL;
Hello I am writing this in Postgres,
I have 2 tables that I want to join.
The first one is named Contract and has let's say 3 fields: ID, Category and DateOfSigning
and the second one is named ContractCategory and has 3 fields : ID and ContractCategory and Cost
The Category of Contract is a foreign key to the ContractCategory in the respective table and the
ContractCategory's ID is a foreign key to the Contract ID.
What I am looking to do is to get the Category with the Maximum Cost for the Company.
So in order to do this, I get the sum of each Category in the Contract Table with the following command:
select "Category", Count("Category") from "Contract" group by "Category"
which returns the categories and their sum in the table.
After, I join this with the ContractCategory table to get the total Profit for each category on their IDs with the following command:
select "Category","count"*"Cost" as "MaxProfit" from ("ContractCategory" inner join(
select "Category", Count("Category") from "Contract" group by "Category") as D on ("ContractCategory" = "Category")))
This returns each contract and the total Profit each one gives.
Then, I want to select the whole row where the Profit is Maximum. What I do is this command which returns 1 row: Category, TotalProfit.
select "Category","Profit" from(
select Max("TotalProfit") as "Profit" from(
select "Category","count"*"Cost" as "TotalProfit" from ("ContractCategory" inner join(
select "Category", Count("Category") from "Contract" group by "Category") as D on ("ContractCategory" = "Category"))) AS B) as F
inner join(
select "Category","count"*"Cost" as "MaxProfit" from ("ContractCategory" inner join(
select "Category", Count("Category") from "Contract" group by "Category") as D on ("ContractCategory" = "Category"))) AS H
on ("Profit" = "MaxProfit");
I am sure there is a way from the 2nd command to get the whole row but I can't find a way to do it other than the 3rd command which is probably too complex. Is there a way to return the Max value AND the Category this value belongs to?
Thank you.
You wouldn't use max(). If you want one row returned, you would use order by and limit/fetch first.
I find your question really hard to follow -- no sample data, no desired results, no simple explanation of what you want to do. But if you wanted the category with the maximum profit, it would look something like this:
select cc.Category, sum(cost)
from contract c join
contractcategory cc
on c.ContractCategory = cc.Category
group by cc.Category
order by sum(cost) desc
limit 1;
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
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 :)
Short:
From below sql select I get the cart_id and the value of the maximum valued item in that cart.
SELECT CartItems.cart_id, MAX(ItemValues.value)
FROM CartItems
INNER JOIN ItemValues
ON CartItems.item_id=ItemValues.item_id
GROUP BY CartItems.cart_id
but I also need item_id for that item (ItemValues.item-id).
Long:
Two tables, CartItems, ItemValues (and their respective Carts, Items, irrelevant here).
Each cart can have several items wheras each item has one value defined in ItemValues.
Each item belongs to one cart.
The value of a cart is the value of the item with maximum value within its cart.
How do I select cart-id, max(item-value) and it's corresponding item-id?
For instance cart-id A contains item-id X with value 10 and item-id Y with value 90.
With above sql select I get, A, 90
What I need is
A, Y, 90
platform: MS SQL
In MS SQL and Oracle:
SELECT *
FROM
(
SELECT ci.*, iv.*,
ROW_NUMBER() OVER (PARTITION BY CartItems.cart_id ORDER BY ItemValues.value DESC)
FROM CartItems ci
INNER JOIN ItemValues iv
ON CartItems.item_id=ItemValues.item_id
) s
WHERE rn = 1
In MySQL:
SELECT
FROM
(
SELECT ci.*,
(
SELECT id
FROM ItemValues iv
WHERE iv.item_id = ci.item_id
ORDER BY
value DESC
LIMIT 1
) AS maxitem
FROM CartItems ci
) iv, ItemValues ivo
WHERE ivo.id = iv.maxitem
This code was written for Oracle, but should be compatible with most SQL versions:
This gets the max(high_val) and returns its key.
select high_val, my_key
from (select high_val, my_key
from mytable
where something = 'avalue'
order by high_val desc)
where rownum <= 1
What this says is: Sort mytable by high_val descending for values where something = 'avalue'. Only grab the top row, which will provide you with the max(high_val) in the selected range and the my_key to that table.