I have 3 tables and my query is :
SELECT BRAND, AMOUNT FROM
(
SELECT BRAND, AMOUNT FROM SALES1
UNION
SELECT BRAND, AMOUNT FROM SALES2
UNION
SELECT BRAND, AMOUNT FROM SALES3
)
SALES 1 TABLE HAS BRAND: A AND AMOUNT: 50
SALES 3 TABLE HAS BRAND: A AND AMOUNT: 100
I want to get the amount 50 and disregard 100. I want to ask if is there any priority when using union?
If you want the first occurrence, you should use union all rather than union. This is important for performance reasons, because union does unnecessary duplicate elimination.
Then use the not exists clauses for each subquery:
(SELECT BRAND, AMOUNT
FROM SALES1
) UNION ALL
(SELECT BRAND, AMOUNT
FROM SALES2 s2
WHERE NOT EXISTS (SELECT 1 FROM SALES1 s1 WHERE s1.BRAND = s2.BRAND)
) UNION ALL
(SELECT BRAND, AMOUNT
FROM SALES3 s3
WHERE NOT EXISTS (SELECT 1 FROM SALES1 s1 WHERE s1.BRAND = s3.BRAND) AND
NOT EXISTS (SELECT 1 FROM SALES2 s2 WHERE s2.BRAND = s3.BRAND)
)
SELECT BRAND, AMOUNT
FROM
( SELECT BRAND, AMOUNT, 1 AS priority
FROM SALES1
UNION ALL
SELECT BRAND, AMOUNT, 2 AS priority
FROM SALES2
UNION ALL
SELECT BRAND, AMOUNT, 3 AS priority
FROM SALES3
)
ORDER BY priority
LIMIT 1;
you need a "where not exists"(or "not in" or a "left join") within your unions:
(SELECT BRAND, AMOUNT FROM SALES1 )
UNION
(SELECT BRAND, AMOUNT FROM SALES2)
UNION
(SELECT BRAND, AMOUNT FROM SALES3 where brand not in (SELECT BRAND FROM SALES1))
Related
Below is my query to get some data for dashboard screen.
SELECT COUNT(*) as occupied_rooms FROM rooms where available='N' ;
SELECT COUNT(*) as checkedIn_guests FROM booking where checkout_time='' ;
SELECT COUNT(*) as available_rooms FROM rooms where available='Y' ;
SELECT COUNT(*) as total_guest FROM booking;
SELECT COUNT(*) as total_booking FROM booking;
SELECT COUNT(*) as total_staff FROM employee;
It produce output as show in above
How ever I want the output like given above image.
Use union all
SELECT 'occupied_rooms' as which, COUNT(*) as cnt FROM rooms where available = 'N'
UNION ALL
SELECT 'checkedIn_guests', COUNT(*) FROM booking where checkout_time = ''
UNION ALL
SELECT 'available_rooms', COUNT(*) FROM rooms where available = 'Y' ;
UNION ALL
SELECT 'total_guest', COUNT(*) FROM booking;
UNION ALL
SELECT 'total_booking', COUNT(*) FROM booking;
UNION ALL
SELECT 'total_staff', COUNT(*) FROM employee;
You could make the query a bit more efficient by combining the queries that reference the same table. But the overall structure would be essentially the same.
You could use a UNION for build single table result with each result in a row
SELECT 'occupied_rooms', COUNT(*) count
FROM rooms
where available='N'
UNION
SELECT 'checkedIn_guests', COUNT(*)
FROM booking
where checkout_time=''
UNION
SELECT 'available_rooms', COUNT(*)
FROM rooms
where available='Y'
UNION
SELECT 'total_guest', COUNT(*)
FROM booking
UNION
SELECT 'total_booking', COUNT(*)
FROM booking
UNION
SELECT 'total_staff', COUNT(*)
FROM employee;
Hi below is my sql query as
SELECT
o.OrderNumber,
oi.Sku,
Sum(Isnull(oi.Price * oi.Quantity,0)) as Price,
DENSE_RANK() over(partition by o.orderNumber order by oi.sku) as CouponRowId
from ac_OrderItems oi
inner join ac_Orders o on oi.OrderId = o.OrderId
Inner Join ac_OrderShipments os on oi.OrderShipmentId =os.OrderShipmentId
WHERE (oi.OrderItemTypeId IN (5))
group by o.OrderNumber, oi.Sku
and below is the record I am getting
OrderNumber Sku Price CouponRowId
90061 BLACKBERRY -5.6900 1
90061 LEMON -5.6900 2
90061 PEACH -5.6900 3
90061 SHIP100 -10.920 4
but I want my record as
OrderNumber Sku Price
90061 BLACKBERRY -5.6900
LEMON -5.6900
PEACH -5.6900
SHIP100 -10.920
I want that if order number is same in that case all detail record should come in 1st row and then after other record should only show Sku and price only and also we need to remove the DENSE_RANK() column
By seeing the query seems like Partition Clause can help you to
resolve the issue. Please look at the below query. I am not so sure
about the data model, but looks like you need to partition by using
the OrderNumber column. Please replace the query in the first CTE with your actual table which will be like the second query. I cant test it since I don't have the environment. Please test the query
;WITH CTE_Table
AS
(
SELECT 90061 'OrderNumber' , 'BLACKBERRY' Sku, -5.6900 'Price', 1 'CouponRowId' UNION
SELECT 90061, 'LEMON', -5.6900, 2 UNION
SELECT 90061, 'PEACH', -5.6900, 3 UNION
SELECT 90061, 'SHIP100', -10.920, 4 UNION
SELECT 90062 'OrderNumber' , 'BLACKBERRY' Sku, -5.6900 'Price', 1 'CouponRowId' UNION
SELECT 90062, 'LEMON', -5.6900, 2 UNION
SELECT 90062, 'PEACH', -5.6900, 3 UNION
SELECT 90062, 'SHIP100', -10.920, 4
),
CTE_New
AS
(
SELECT *, ROW_NUMBER() OVER(PARTITION BY OrderNumber ORDER BY OrderNumber) Patrn FROM CTE_Table
)
SELECT CASE WHEN Patrn =1 THEN CONVERT(VARCHAR(10),OrderNumber) ELSE '' END OrderNumber, Sku, Price, CouponRowId FROM CTE_New
;WITH CTE_Table
AS
(
SELECT
o.OrderNumber,
oi.Sku,
Sum(Isnull(oi.Price * oi.Quantity,0)) as Price,
DENSE_RANK() over(partition by o.orderNumber order by oi.sku) as CouponRowId
from ac_OrderItems oi
inner join ac_Orders o on oi.OrderId = o.OrderId
Inner Join ac_OrderShipments os on oi.OrderShipmentId =os.OrderShipmentId
WHERE (oi.OrderItemTypeId IN (5))
group by o.OrderNumber, oi.Sku
),
CTE_New
AS
(
SELECT *, ROW_NUMBER() OVER(PARTITION BY OrderNumber ORDER BY OrderNumber) Patrn FROM CTE_Table
)
SELECT CASE WHEN Patrn =1 THEN CONVERT(VARCHAR(10),OrderNumber) ELSE '' END OrderNumber, Sku, Price, CouponRowId FROM CTE_New
Seeing your comment this is an attempt to solve it on the query itself (I assumed CouponRowID might do the job, if OrderNumber is unique):
WITH
tmp AS (
SELECT o.OrderNumber, oi.Sku, SUM(ISNULL(oi.Price * oi.Quantity, 0)) AS Price, DENSE_RANK() OVER (PARTITION BY o.orderNumber ORDER BY oi.sku) AS CouponRowId
FROM ac_OrderItems oi
INNER JOIN ac_Orders o ON oi.OrderId=o.OrderId
INNER JOIN ac_OrderShipments os ON oi.OrderShipmentId=os.OrderShipmentId
WHERE(oi.OrderItemTypeId IN (5))
GROUP BY o.OrderNumber, oi.Sku
)
SELECT CASE WHEN tmp.CouponRowId=1 THEN tmp.OrderNumber END AS OrderNumber, tmp.Sku, tmp.Price
FROM tmp
ORDER BY tmp.OrderNumber, tmp.SKu;
Sorry....! I cant understand your explanations..
I just worked only for get your expected OP...
create table #ac_OrderItems(id varchar(20) --varchar, i used instead of int.Beside, varchar is easy to change to int.
, Sku varchar(20), Price decimal, CouponRowId int)
insert into #ac_OrderItems values(
90061 , 'BLACKBERRY' , -5.6900 , 1)
,(90061, 'LEMON', -5.6900, 2 )
,(90061, 'PEACH', -5.6900, 3 )
,(90061, 'SHIP100', -10.920, 4 )
,(90062 , 'BLACKBERRY' ,-5.6900 , 1 )
,(90062, 'LEMON', -5.6900, 2 )
,(90062, 'PEACH', -5.6900, 3 )
,(90062, 'SHIP100', -10.920, 4)
select * from #ac_OrderItems
;with
orders(id, sku, price, couponId, rn)
as
(
select *, ROW_NUMBER() over(partition by id order by id) from #ac_OrderItems
)select iif(rn = 1,id,''),sku,price,couponId from orders
-- if i used int, empty is denoted by 0. But you want '' this. So i used varchar id
let you know me, what you got.
I have a 80 tables and I want to filter who has the highest price among 80 tables. I plan on using this query:
SELECT id
FROM (SELECT id, price FROM T1 WHERE price = (SELECT MAX(price) FROM T1)
UNION
SELECT id, price FROM T2 WHERE price = (SELECT MAX(price) FROM T2)
UNION
SELECT id, price FROM T3 WHERE price = (SELECT MAX(price) FROM T3)
) AS M
ORDER BY price DESC
LIMIT 1
But I find it inefficient. Is there other way?
I think this would be a lot faster.
SELECT id, price FROM t1
UNION SELECT id, price FROM t2
UNION SELECT id, price FROM t3
ORDER BY price DESC
LIMIT 1
This question is an extension to this earlier question (not asked by me).
I have a table consisting of these fields:
id | date_from | date_to | price | priceName
--------------------------------------------------------
CK1 22-12-2012 29-12-2012 800 low
CK1 22-12-2012 29-12-2012 1200 medium
CK2 22-12-2012 29-12-2012 1400 high
CK2 22-12-2012 29-12-2012 1800 very high
CK2 22-12-2012 29-12-2012 2200 extortionate
How do I create a SQL select that groups the results by ID, DATE_FROM, DATE_TO and picks the lowest value from price and the priceName that is associated with the lowest price?
So the result would be
CK1 22-12-2012 29-12-2012 800 low
CK2 22-12-2012 29-12-2012 1400 high
From the previous question I can do:
select id, date_from, date_to, min(price)
from table
group by id, date_from, date_to
How do I extend this to only select the priceName that matches the min(price)? Grouping by priceName won't work because it does not constrain to the min(price).
You can use subquery.
Select Table.id,Date_from,date_to,MinPrice,PriceName
from
(select id, min(price) as MinPrice
from table
group by id) t1
INNER JOIN table ON t1.id=table.id and t1.MinPrice=table.Price
Group by id,Date_from,date_to,MinPrice,PriceName
Try this:
Select t.*,t1.priceName from (
select id, date_from, date_to, min(price)
from table
group by id, date_from, date_to) t
join table t1 on t.id =t1.id
and t.date_from =t1.date_from
and t.date_to =t1.date_to
and t.price =t1.price
One way would be to use the rank window function:
SELECT id, date_from, date_to, price, priceName
FROM (SELECT id, date_from, date_to, price, priceName,
RANK() OVER (PARTITION BY id, date_from, date_to
ORDER BY price ASC) AS rk
FROM mytable) t
WHERE rk = 1
Using CTE:
WITH cte (id, date_from, date_to, minprice) AS (
SELECT id, date_from, date_to, [minprice] = min(price)
FROM table_name
GROUP BY id, date_from, date_to)
SELECT
c.id, c.date_from, c.date_to, c.[minprice], t.priceName
FROM table_name t
JOIN cte c
ON t.id = c.id
AND t.date_from = c.date_to
AND t.data_to = c.date_to
I have a table Like below.
I want the product_id of Minimum, Maximum and Average cost products in a single query.
CREATE TABLE productlist(product_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
cost INT);
INSERT INTO productlist(cost)
VALUES('2450'),
('2200'),
('2580'),
('2405'),
('3500'),
('1500'),
('1800'),
('1520'),
('1740'),
('1940'),
('2940'),
('1250'),
('1290'),
('1390'),
('2900');
Output:
Min 12
Max 5
Avg 2093
I tried like one below but its not working.
SELECT product_id, MIN(cost) as mincost
FROM productlist
GROUP BY product_id
ORDER BY mincost ASC
LIMIT 0,1
UNION
SELECT product_id, max(cost) as maxcost
FROM productlist
GROUP BY product_id
ORDER BY maxcost DESC
LIMIT 0,1
How should I do this
select 'Min', product_id
from productlist
where cost = (select min(cost) from productlist)
UNION
select 'Max', product_id
from productlist
where cost = (select MAX(cost) from productlist)
UNION
select 'Avg', round(AVG(cost),0) as Avg
from productlist
select product_id, cost
from productlist where cost = (SELECT max(cost)from productlist)
union
select product_id, cost
from productlist where cost = (SELECT min(cost)from productlist)
union
select product_id, cost
from productlist where cost = (SELECT x.cost from productlist x, productlist y
GROUP BY x.cost
HAVING SUM(SIGN(1-SIGN(y.cost-x.cost))) = (COUNT(*)+1)/2)
This uses median, returns product id in every case
the output you want is not coming by the query you wrote
you need to try out this one for getting the required output
select 'Min', product_id
from productlist
where cost = (select min(cost) from productlist)
UNION
select 'Max', product_id
from productlist
where cost = (select MAX(cost) from productlist)
UNION
select 'Avg', floor(AVG(cost)) as Avg
from productlist
This answers your question exactly but it should be noted that it costs 3 table scans to find this data. Also, the example in the question suggests that the average value is truncated down to 2093 from 2093.67. It is perhaps better to replace this with round.
SQL Fiddle
SELECT concat('Min ', product_id)
FROM productlist
WHERE cost = (SELECT min(cost) from productlist)
UNION ALL
SELECT concat('Max ', product_id)
FROM productlist
WHERE cost = (SELECT max(cost) from productlist)
UNION ALL
SELECT concat('Avg ', truncate(avg(cost), 0))
FROM productlist
This is to select all the products
SELECT
max(cost), MIN(cost), AVG(cost)
FROM
productlist
GROUP BY
product_id
GROUP BY is not exactly required here. But seems like you are beginner, googling to will help you.
For your question try this.
SELECT
(select CONCAT(product_id, '-', cost) from productlist group by product_id order by cost DESC limit 1) as MAX,
(select CONCAT(product_id, '-', cost) from productlist group by product_id order by cost ASC limit 1) as MIN,
(select avg(cost) from productlist) as AVG
FROM
productlist limit 1