Displaying data from multiple tables in Oracle 11g - sql

Question
I want to display a combination of DATA from different tables. In this case all combinations of food and drink, which have not been ordered so far.
My database tables
Customer_order
Orderno(PK) DateOrd DateReq Address
O00001 03-Apr-11 07-Apr-11 Union St
O00002 05-Apr-11 01-May-11 St. Andrew St.
O00003 12-Apr-11 27-Apr-11 Garthdee
O00004 12-Apr-11 17-Apr-11 Union St.
Dish
Dishid(PK) DishName Vegetarian Price
D0001 Pasta bake yes 6.00
D0002 Fish pie No 9.00
D0003 Steak and chips No 14.00
D0004 Stuffed peppers yes 11.50
D0005 Ham and rice No 7.25
D0006 Lamb curry No 8.50
Drink
Drinkid(PK) DrinkName DrinkType Price
DR0001 Water soft 1.00
DR0002 Coffee hot 1.70
DR0003 Wine alcoholic 3.00
DR0004 Beer alcoholic 2.30
DR0005 tea hot 1.50
Food_order
Food_orderno(PK) Orderno(FK) Dishid(FK) NPortions
FO00001 O00001 D0003 6
FO00002 O00001 D0001 4
FO00003 O00001 D0004 3
FO00004 O00002 D0001 10
FO00005 O00002 D0002 10
FO00006 O00003 D0002 35
FO00007 O00004 D0002 23
Drink_order
Drinkorderid(PK) Orderid(FK) Drinkid(FK) N_units
DO00001 O00001 DR0001 13
DO00002 O00001 DR0002 13
DO00003 O00001 DR0004 13
DO00004 O00002 DR0001 20
DO00005 O00002 DR0003 20
DO00006 O00002 DR0004 15
DO00007 O00003 DR0002 35
DO00008 O00004 DR0001 23
DO00009 O00004 DR0003 15
DO00010 O00004 DR0004 15
http://imgur.com/KziEoLo
Queries tried so far
select distinct d.dish_name, dr.drink_name
from Dish d, Drink dr, Food_order fo, Drink_order dro, Customer_order co
where co.orderno = fo.orderno
AND co.orderno = dro.orderno
order by dish_name, drink_name;
select d.dish_name, dr.drink_name
from Dish d, Drink dr, Food_order fo, Drink_order dro, Customer_order co
where co.orderno = fo.orderno
AND co.orderno = dro.orderno
group by d.dish_name, dr.drink_name;
select distinct d.dish_name, dr.drink_name
from Dish d, Drink dr, Food_order fo, Drink_order dro, Customer_order co
where d.dishid = fo.DISHID
AND dr.DRINKID = dro.DRINKID
AND fo.ORDERNO = dro.ORDERNO
group by d.dish_name, dr.drink_name;
select distinct d.dish_name, dr.drink_name
from dish d, drink dr, food_order fo, drink_order do
where fo.ORDERNO = do.ORDERNO
group by d.dish_name, dr.drink_name;

That seems to return, what you are asking for:
SELECT
Dish.DishName,
Dish.Dishid,
Drink.DrinkName,
Drink.Drinkid
FROM Dish
JOIN
(SELECT
Dishid
, Drinkid
FROM Dish
CROSS JOIN Drink
MINUS
(SELECT
Dishid
, Drinkid
FROM Food_order
CROSS JOIN Drink_order
WHERE Food_order.Orderno = Drink_order.Orderid
)
) NotOrderedTogether
ON Dish.Dishid = NotOrderedTogether.Dishid
JOIN Drink
ON NotOrderedTogether.Drinkid = Drink.Drinkid
ORDER BY Dishname, Drinkname
;
See it in action: SQL Fiddle.
As pointed out in the comments, the result set is going to explode, if you add large(r) numbers of food and beverages. In that case, it would probably make sense to apply the MINUS first to dishes and drinks respectively, and to apply the CROSS JOIN to the least possible number of records.
Please comment, if and as this requires adjustment / further detail.

Related

Select sum shown null value in left join SQL statement

I have three tables and expecting the result as below but i do not know how to correct my sql statement.
select history.company,history.ghacct,rpt_revenue.revenue,rpt_revenue.other, isnull(guest.stay,0) as stay, isnull(guest.nights,0) as nights
from history
left join(select company,count(*) as stay,sum(nights) as nights from guest group by company) guest on guest.company=history.company
left join (select ghacct,sum(revenue) as revenue, sum(other) as other
from rpt_revenue group by ghacct) rpt_revenue on rpt_revenue.ghacct=history.ghacct
where history.type='c' group by history.company, history.ghacct,rpt_revenue.revenue, rpt_revenue.other,guest.stay,guest.nights order by history.company asc;
history
ghacct company type
33 JOINT LTD 10010205687 c
3B GLOBAL 10010350619 c
3E FASHION 10010244145 c
3P INT'L 10010112089 c
guest
company stay nights
33 JOINT LTD 01/01/2009 1
33 JOINT LTD 01/06/2009 1
3B GLOBAL 10/02/2019 2
3E FASHION 09/25/2008 6
3P INT'L 08/26/2009 3
3P INT'L 04/26/2010 9
rpt_revenue
ghacct revenue other
10010205687 20 10
10010205687 10 10
10010350619 30 2
10010244145 15 3
10010112089 16 8
10010112089 4 2
Result
company ghacct revenue other stay nights
33 JOINT LTD 10010205687 NULL NULL 2 2
3B GLOBAL 10010350619 NULL NULL 1 2
3E FASHION 10010244145 NULL NULL 1 6
3P INT'L 10010112089 NULL NULL 2 12
Expected result
company ghacct revenue other stay nights
33 JOINT LTD 10010205687 30 20 2 2
3B GLOBAL 10010350619 30 2 1 2
3E FASHION 10010244145 15 3 1 6
3P INT'L 10010112089 20 10 2 12
I think the main problem with your current query lies in the GROUP BY clause, which should really only be aggregating by company and account. In addition, you might want to use ISNULL for the revenue and other amount, as you are already doing so for stay and nights.
SELECT
h.company,
h.ghacct,
ISNULL(rr.revenue, 0) AS revenue,
ISNULL(rr.other, 0) AS other,
ISNULL(g.stay, 0) AS stay,
ISNULL(g.nights, 0) AS nights
FROM history h
LEFT JOIN
(
SELECT company, COUNT(*) AS stay, SUM(nights) AS nights
FROM guest
GROUP BY company
) g
ON g.company = h.company
LEFT JOIN
(
SELECT ghacct, SUM(revenue) AS revenue, SUM(other) AS other
FROM rpt_revenue
GROUP BY ghacct
) rr
ON rr.ghacct = h.ghacct
WHERE
h.type = 'c'
GROUP BY
h.company,
h.ghacct
ORDER BY
h.company;

retrieving data from field which has multiple values

We have table person. It has sample fields with multiple values like
person
ID name tripNumber startPlace endPlace
1 xxx 20 Portland Atlanta
25 California Atlanta
40 America Africa
2 EKVV 40 America Africa
37 Argentina Carolina
We need to retrieve entire row of data in particular condition like tripNumber=40 and endPlace="Africa"
We need the result like this,
ID name tripNumber startPlace endPlace
1 xxx 40 America Africa
2 EKVV 40 America Africa
Below is for BigQuery Standard SQL
#standardSQL
WITH `project.dataset.person` AS (
SELECT 1 id, 'xxx' name, [20, 25, 40] tripNumber, ['Portland', 'California', 'America'] startPlace, ['Atlanta', 'Atlanta', 'Africa'] endPlace UNION ALL
SELECT 2, 'EKVV', [40, 37], ['America', 'Argentina'], ['Africa', 'Carolina']
)
SELECT id, name, tripNumber, startPlace[SAFE_OFFSET(off)] startPlace, endPlace[SAFE_OFFSET(off)] endPlace
FROM `project.dataset.person`,
UNNEST(tripNumber) tripNumber WITH OFFSET off
WHERE tripNumber = 40
with result
Row id name tripNumber startPlace endPlace
1 1 xxx 40 America Africa
2 2 EKVV 40 America Africa
Above solution assumes that you have independent repeated fields and match to be done based on positions in respective arrays
Below - is based on more common pattern of having repeated record
so if person table would look like below
Row id name trips.tripNumber trips.startPlace trips.endPlace
1 1 xxx 20 Portland Atlanta
25 California Atlanta
40 America Africa
2 2 EKVV 40 America Africa
37 Argentina Carolina
in this case solution would be
#standardSQL
WITH `project.dataset.person` AS (
SELECT 1 id, 'xxx' name, [STRUCT<tripNumber INT64, startPlace STRING, endPlace STRING>(20, 'Portland', 'Atlanta'),(25, 'California', 'Atlanta'),(40, 'America', 'Africa')] trips UNION ALL
SELECT 2, 'EKVV', [STRUCT(40, 'America', 'Africa'),(37, 'Argentina', 'Carolina')]
)
SELECT id, name, tripNumber, startPlace, endPlace
FROM `project.dataset.person`,
UNNEST(trips) trip
WHERE tripNumber = 40
with result
Row id name tripNumber startPlace endPlace
1 1 xxx 40 America Africa
2 2 EKVV 40 America Africa

Items in one location not in another. SQL

I'm trying to query, possibly with a self-join, to find which Products are on sale in Chicago that are not on sale in Miami.
ProductID Product_Type On Sale Stock_location
2201 Cereal Y chicago
2202 Beverage Y chicago
2203 Frozen Food y chicago
2204 Poultry N chicago
2205 Health N chicago
2206 Snacks Y chicago
2207 Household N chicago
2208 Personal N chicago
2209 Produce N chicago
2201 Cereal Y Miami
2202 Beverage Y Miami
2203 Frozen Food N Miami
2204 Poultry Y Miami
2205 Health N Miami
2206 Snacks Y Miami
2207 Household N Miami
2208 Personal N Miami
It's something like below
select Product_Type from Products
where [On Sale] = 'Y' and
Stock_location = 'chicago' and
Product_Type not in (Select Product_Type form Products where [On Sale] = 'N' and Stock_location = 'Miami' )
SELECT t1.*
FROM t AS t1
JOIN t AS t2 ON ( t1.Product_Type = t2.Product_Type )
WHERE t1.On_Sale = "Y"
AND t2.On_Sale = "N";
Useful resource:
https://www.w3schools.com/sql/sql_join_self.asp

How to statistics sales, city, customer of goods use oracle

I have a oracle view, and include the sale of goods details. It like this:
OrderId OrderDetailId GoodsId GoodsName UnitName SalesQty Price CustomerName Country City
200138 ddd0a3b42adb 770 A bag 5 18.00 AAAA USA NewYork
223448 70ca7ceb41c7 193 D bottle 10 10.00 BBB USA NewYork
200118 ab472857573e 1286 F cup 8 50.00 CCC China Beijing
244028 230a43920667 770 A bag 20 18.00 CCC China Beijing
251118 118fc2b3839b 5929 C box 40 6.00 DDDD Japan Tokyo
200000 abd0a3b42ddd 770 A bag 15 18.00 AAAA USA NewYork
111118 11111113839b 5929 C box 40 6.00 FFFF Japan Tokyo
And I want a SQL statement statistics sales, the number of cities, the number of customers of each goods. The result should be like this:
GoodsId GoodsName SalesQty(UnitName) CityQty CustomerQty
GoodsId GoodsName SalesQty(UnitName) CityQty CustomerQty
770 A 40(bag) 2 2
193 D 10(bottle) 1 1
1286 F 8(cup) 1 1
5929 C 80(box) 1 2
How to write sql statistical statement? Thanks!
Simply use GROUP BY
select GoodsId, GoodsName, UnitName,
sum(SalesQty) SalesQty,
count(distinct City) CityQty,
count(distinct CustomerName) CustomerQty
from goods_view
group by GoodsId, GoodsName, UnitName
demo
You may use cube, to include also sub&grand totals of quantities :
select GoodsId, GoodsName||'('||UnitName||')' GoodsName,
sum(SalesQty) SalesQty, count(distinct City) CityQty, count(distinct CustomerName) CustomerQty
from v_goods
group by cube(GoodsId, GoodsName||'('||UnitName||')')
order by GoodsId,GoodsName||'('||UnitName||')';

Suggestion of a simple SQL query

I have the following table:
state product_a product_b final_score
FL Apple Açai Berries 9
FL Apricot Banana 15
FL Avocado Coconut 5
FL Bilberry Apricot 17
FL Blackcurrant Apricot 6
FL Blackcurrant Boysenberry 12
FL Blueberry Avocado 11
FL Blueberry Cantaloupe 6
FL Cantaloupe Coconut 1
FL Currant Blackcurrant 5
FL Cherry Currant 10
FL Cherimoya Cherry 6
FL Cherimoya Date 14
FL Cloudberry Blueberry 16
FL Coconut Apricot 14
FL Cranberry Damson 1
FL Date Banana 5
NY Apricot Blackcurrant 5
NY Apricot Dragonfruit 15
NY Avocado Cherimoya 16
NY Avocado Coconut 18
NY Banana Damson 14
NY Bilberry Apricot 16
NY Bilberry Avocado 1
NY Blackberry Blackcurrant 20
NY Blackberry Cherimoya 12
NY Blackcurrant Damson 19
Based on "state" and "product_A" I need to return "product_B" with the highest "final_score".
For instance, if I check for NY "state", "product_A" Blackberry, I want my query to return Blackcurrant.
For instance, I used the following query:
select product_b from PRODUCTSUGGESTION a,
(select max(final_score) maxscore from PRODUCTSUGGESTION
where product_A like '%Blackcurrant%' and state like 'FL') r
where r.maxscore=final_score and product_A like '%Blackcurrant%' and state like 'FL'
The output would be: Boysenberry
The query I presented above gives me the wanted output. However, I know that joins increase the query complexity. Could anyone suggest another way of doing it with a simpler query?
Seems like this is too simple to me, but here you go:
SELECT product_b FROM PRODUCTSUGGESTION
WHERE state = 'FL' AND product_a = 'Blackcurrant'
ORDER by final_score DESC FETCH FIRST 1 ROW ONLY
You need calculate the maxScore first. Then join both tables to get the name.
SQL Fiddle Demo
This use sql server cte, MySql need inner select instead.
WITH maxScore as (
SELECT state, product_a, max(final_score) as final_score
FROM Table1
GROUP BY state, product_a
)
SELECT t.*, m.final_score
FROM Table1 t
inner join maxScore m
on t.state = m.state
and t.product_a = m.product_a
and t.final_score = m.final_score