Write a query to get output as shown below - sql

A table name player having some columns & data in the table are as follows:
**PID**|**PNAME**|**CITY**|**TEAM**|**SALARY**|**NO_OF_PENALTIES**
1001 ozil istanbul germany 500000 1
1002 messi madrid arsenal 500000 2
1003 ronaldo manc uk 600000 1
1004 puyol sussex germany 400000 3
1005 fabregas manchester uk 450000 2
1006 costa ankara turkey 400000 3
1007 beckham london uk 600000 2
This is the table.Write a query I want record if team name is "germany" & no_of_penalties=1 then I want to get the record.If team name is "uk" & no_of_penalties=2 then I don't want to get the record.
Mean according to the above records as per the query I want to get the record having pid=1001 & pid=1003.
But when I write the query as shown below:
select * from player where (team='germany' and no_of_penalties=1) or not (team='uk' and no_of_penalties=2) and team in ('germany','uk');
Then after execute above query the output looks like having pid=1001, 1003, 1004 as shown below
**PID**|**PNAME**|**CITY**|**TEAM**|**SALARY**|**NO_OF_PENALTIES**
1001 ozil istanbul germany 500000 1
1003 ronaldo manc uk 600000 1
1004 puyol sussex germany 400000 3
So could you please solve me the problem?

Try this one
select * from player
where (team='germany' and no_of_penalties=1)
or (team='uk' and no_of_penalties!=2)

Select * From Player Where
(Team = 'Germany' AND No_Of_Penalties = 1)
AND NOT
(Team = "UK" AND No_Of_Penalties = 2)
Forgive me if I am wrong as I find your question hard to understand clearly but you put "If team name is "uk" & no_of_penalties=2 then I don't want to get the record" meaning you dont want the value of 2 however the answer you selected will show those with value of 2

Try out
select * from player
where (team='germany' and no_of_penalties=1)
union all
select * from player
where (team='uk' and no_of_penalties!=2)

These are mutually exclusive data, so it should be with AND (not OR). Try this
SELECT *
FROM player
WHERE (
team = 'germany'
AND no_of_penalties = 1
)
AND NOT (
team = 'uk'
AND no_of_penalties = 2
)
AND team IN (
'germany'
,'uk'
) );

Related

how to filter based on events that HAVE happened and HAVE NOT happened

I have a table named orders in a SQL database that looks like this:
user_id email segment destination revenue
1 joe#smith.com basic New York 500
1 joe#smith.com luxury London 750
1 joe#smith.com luxury London 500
1 joe#smith.com basic New York 625
1 joe#smith.com basic Miami 925
1 joe#smith.com basic Los Angeles 218
1 joe#smith.com basic Sydney 200
2 mary#jones.com basic Chicago 375
2 mary#jones.com luxury New York 1500
2 mary#jones.com basic Toronto 2800
2 mary#jones.com basic Miami 750
2 mary#jones.com basic New York 500
2 mary#jones.com basic New York 625
3 mike#me.com luxury New York 650
3 mike#me.com basic New York 875
4 sally#you.com luxury Chicago 1300
4 sally#you.com basic New York 1200
4 sally#you.com basic New York 1000
4 sally#you.com luxury Sydney 725
5 bob#gmail.com basic London 500
5 bob#gmail.com luxury London 750
Here's a SQL Fiddle: http://www.sqlfiddle.com/#!9/22f40a/1
I'd like to be able to apply the following logic to get the final result set:
Return only the distinct user_id and the user's email based on the following conditions:
where segment is equal to luxury and destination is equal to New York
OR
where segment is equal to luxury and destination is equal to London
OR
where segment is equal to basic and destination is equal to New York and the given user has a revenue amount in the basic and New York records that sums to greater than $2,000
BUT
a given user has not previously been to destination equal to Miami
Based on my sample data, I would like to see the following returned:
user_id email
3 mike#me.com
4 sally#you.com
5 bob#gmail.com
I tried to use the following to get part of what I need:
SELECT
DISTINCT(user_id),
email
FROM orders o
WHERE
(o.segment = 'luxury' AND o.destination = 'New York')
OR
(o.segment = 'luxury' AND o.destination = 'London')
But, this query doesn't handle conditions #3 and #4 above. I feel like a window function might be helpful here, but I don't know quite how to implement it.
If someone could help me with this query, I would be incredibly grateful!
Thanks!
You can use subqueries to achieve what you need:
SELECT
DISTINCT(o.user_id),
o.email
FROM orders o
WHERE
(
-- Clause 1
(o.segment = 'luxury' AND o.destination = 'New York')
OR
-- Clause 2
(o.segment = 'luxury' AND o.destination = 'London')
OR
-- Clause 3
(o.user_id IN (
SELECT DISTINCT(o.user_id)
FROM orders o
WHERE o.segment = 'basic' AND o.destination = 'New York'
GROUP BY o.user_id, o.email, o.segment, o.destination
HAVING SUM(o.revenue) > 2000
))
)
AND
-- Clause 4
o.user_id NOT IN (
SELECT DISTINCT(o.user_id)
FROM orders o
WHERE o.destination = 'Miami'
)
here's another to do it by scanning the table once, group by and having:
SELECT user_id, email,
SUM(case
when segment='luxury' and destination in ('New York','London') then 1
else 0
end) as is_luxury,
SUM(case
when segment='basic' and destination in ('New York') then 1
else 0
end) as is_basic,
SUM(case
when segment='basic' and destination in ('New York') then revenue
else 0
end) as basic_revenue,
SUM(case when destination in ('Miami') then 1 else 0 end) as is_miami
FROM orders
GROUP BY 1,2
HAVING (is_luxury > 0 OR (is_basic > 0 AND basic_revenue > 2000))
AND NOT is_miami;

Crosstab query to get results of three tables based on results table

This request might be asked many times but I have done a search last night to figure out but I came up with nothing.
I have three tables
Table A
ID
City
1
LA
2
NY
3
LV
Table B
ID
Job
11
Programmer
22
Engineer
33
Database Administrator
44
Cyber Security Analyst
Table C
ID
Job level
111
Junior
222
Associate
333
Senior
444
Director
Final table
ID
EmployeeName
City_ID
Job_ID
Level_ID
1000
Susie
1
11
333
1001
Nora
2
11
222
1002
Jackie
2
22
111
1003
Mackey
1
11
444
1004
Noah
1
11
111
I’d like to have a crosstab query using Microsoft Access that returns the following result ( based on city )
LA Table
Jobs
Junior
Associate
Senior
Director
Programmer
1
-
1
1
Engineer
-
-
-
-
Database Administrator
-
-
-
-
Cyber Security Analyst
-
-
-
-
How can I do it?
The best approach for this is always:
Create a "base" query that joins the base tables and returns all data columns that you will need for the crosstab query.
Run the crosstab query wizard using the "base" query as input.

Join multiple tables and pick results from most recent table

I have 4 tables. I want all the rows and cols from my first table tbl_2021 and only those data which are not in tbl_2021 but present in the the rest 3 tables, but based on one condition
if there id exist in tbl_2020, tbl_2019 and in tbl_2018 then i need the id and it's details from the most recent table that is tbl_2020.
if an id is across 2019 and 2018 table, then i need the data from 2019 so on like that.If in 2020 and 018 then 020 and so on
if the same is across 2021,2020,2019 and 2018 then the data from 2021 is selected.
And - I'm hail from a shell scripting background, and i've just started with sql. so if any noble mind could tell me the approach or what i should do to get these pieces together would mean more than happiness to me. Thank you
tbl_2021
id
name
addr
location
country
contintent
gdp
123
rob
dware
texas
us
us
8
456
lilly
gwood
london
uk
uk
5
670
rick
utown
newyrok
us
us
8
490
zang
kcity
hk
hongkong
hongkong
6
tbl_020
id
location
name
999
ger
roger
888
bel
leslie
670
us
marie
tbl_019
id
location
name
data
network
999
uk
roger
xx
na
555
rus
vladmir
ux
na
879
us
marie
xx
ua
481
cn
kim
tbl_018
id
location
name
data
network
823
uk
roger
xx
na
555
rus
vladmir
ux
na
879
us
maria
xx
ua
670
us
marie
xy
uy
888
in
raj
xx
jo
output:
id
name
addr
location
country
contintent
gdp
123
rob
dware
texas
us
us
8
456
lilly
gwood
london
uk
uk
5
670
rick
utown
newyrok
us
us
8
490
zang
kcity
hk
hongkong
hongkong
6
999
roger
ger
888
leslie
bel
555
vladmir
rus
879
marie
us
481
kim
cn
823
roger
uk
First, you should fix your data model. It is not a good idea to store such data in separate tables. Instead, you should store in a single table with a year column.
Second, I think you can solve your problem using full join, but it is a little tricky:
select coalesce(t21.id, t20.id, t19.id, t18.id) as id,
coalesce(t21.name, t20.name, t19.name, t18.name) as name,
t21.addr,
. . .
from tbl_2021 t21 full join
tbl_2020 t20
on t21.id = t20.id full join
tbl_2019 t19
on t19.id = coalesce(t21.id, t20.id) full join
tbl_2018 t18
on t18.id = coalesce(t21.id, t20.id, t19.id);
You need to carefully figure out how the columns should be pulled from the different tables.
First you can union all the data from four tables with union all. Then with row_number() we need to serialized rows for each id from higher to lower. Finally select one row for each id with highest year .
with cte as
(
select id,name addr ,location ,country, contintent,data,network, row_number()over (partition by id order by sl ) rn from
(
select id,name ,addr ,location , country, contintent,data,network, 1 sl from tbl_21
union all
select id,name ,'' addr ,location ,'' country,'' contintent, data, network, 2 sl from tbl_20
union all
select id,name ,'' addr ,location ,'' country,'' contintent, data,network, 3 sl from tbl_19
union all
select id,name ,'' addr ,location ,'' country,'' contintent, data,network, 4 sl from tbl_18
)t
)
select id,name ,addr ,location ,country, contintent,data,network from cte where rn=1

How to assign equal revenue weight to every location of a company in a table? Google Big Query

I am working on a problem where I have the following table:
+----------+ | +------+ | +------------+
company_id | country | total revenue
1 Russia 1200
2 Croatia 1200
2 Italy 1200
3 USA 1200
3 UK 1200
3 Italy 1200
There are 3 companies in this table, but company '2' and company '3' have offices in 2 and 3 countries respectively. All companies pay 1200 per month, and because company 2 has 2 offices it shows as if they paid 1200 per month 2 times, and because company 3 has 3 offices it shows as if it paid 1200 per month 3 times. Instead, I would like revenue to be equally distributed based on how many times company_id appears in the table. company_id will only appear more than once for every additional country in which a company is based.
Assuming each company always pays 1,200 per month, my desired output is:
+----------+ | +------+ | +------------+
company_id | country | total revenue
1 Russia 1200
2 Croatia 600
2 Italy 600
3 USA 400
3 UK 400
3 Italy 400
Being new to SQL, I was thinking this can maybe be done through CASE WHEN statement, but I only learned to use CASE WHEN when I want to output a string depending on a condition. Here, I am trying to assign equal revenue weight to each company's country, depending on in how many countries a company is based in.
Thank you in advance for you help!
Below is for BigQuery Standard SQL
#standardSQL
SELECT company_id, country,
total_revenue / (COUNT(1) OVER(PARTITION BY company_id)) AS total_revenue
FROM `project.dataset.table`
If to apply to sample data from your question - output is
Row company_id country total_revenue
1 1 Russia 1200.0
2 2 Croatia 600.0
3 2 Italy 600.0
4 3 USA 400.0
5 3 UK 400.0
6 3 Italy 400.0

SQL - Count after Table Joins

I'm doing a class assignment and seem to be having some trouble with one question. The question requires me two join 3 tables and count the overall number of occurrences for each row.
This is the join command I have so far (need to figure out where I can put a nested count(distinct):
SELECT litwork.btitle,
bookcopy.copy_num,
request.rdate
FROM litwork,
bookcopy,
request
WHERE litwork.lit_id = bookcopy.lit_id
AND bookcopy.persidh = request.persid
ORDER BY btitle;
The join gives me this table as result:
BTITLE COPY_NUM RDATE
--------------- -------------- -------
Bankers 2 18-oct-2012
Bankers 2 30-oct-2012
Blue Ridge 1 20-oct-2012
Linux 1 18-oct-2012
Linux 1 30-oct-2012
My Life 3 31-oct-2012
O-O Design 1 30-oct-2012
O-O Design 3 25-oct-2012
O-O Design 3 18-oct-2012
So how would I make a count(distinct) for all three column within that one command? I'm using standard SQL
Edit to add question prompt (copied and paste):
Show how many requests and how many copies exist for each book that is requested. Show title, number of requests, number of copies of the book. Show in order by title. The SQL query for this question mixes a join with count. To understand such a query, be aware that the join must be processed before the count function .
Be also aware that the join may create duplicate data, so that you should use the count(distinct ..) form of count where needed. (Suggestions: if you have trouble with this question, look at the results of the join without count and group, and figure out how you would perform the required count if these results were data of an existing table. Please do not show this extra query in your report.).
Assumption: a given customer may not have more than one request of the same book.. Note that when joining the table REQUEST with the table BOOK_COPY, the number of rows where a given book appears is the product of the number of requests for that book and of the number of copies.
UPDATE: It's still not 100% correct..
Additional Tables used for the Join (First one is LITWORK table, second one is REQUEST table, and last one is BOOKCOPY table)
LIT_ID BTITLE YEAR
---------- --------------- ----------
1001 The Trojans 2000
1002 My Life 2001
1003 Nature 1998
1004 Blue Ridge 1996
1005 True Java 2012
1006 CPlus 2004
1007 Streaming 2000
1008 MyApps 1998
1009 O-O Design 2012
1010 Camping 1978
1011 Bankers 1970
1012 Linux 1962
LIT_ID PERSID BNAME RDATE RTIME
---------- ---------- -------- ----------- ----------
1001 11 College 18-oct-2012
1001 7 College 25-oct-2012
1003 8 La Jolla 20-oct-2012
1005 7 Pacific 18-oct-2012
1008 11 Atlantic 30-oct-2012
1008 1 College 30-oct-2012
1012 4 La Jolla 31-oct-2012
LIT_ID COPY_NUM PERSID_OUT DATE_OUT DATE_DUE PERSIDH HDATE BNAMEP BNAMEC
---------- ---------- ---------- ----------- ----------- ---------- ----------- -------- --------
1001 1 4 13-sep-2012 27-nov-2012 La Jolla
1002 1 Pacific Atlantic
1002 2 1 02-sep-2012 12-oct-2012 Pacific
1002 3 4 15-nov-2012 La Jolla La Jolla
1003 1 9 10-dec-2012 30-dec-2012 Pacific
1003 2 1 13-dec-2012 22-jan-2013 La Jolla
1003 3 Atlantic Atlantic
1004 1 8 19-nov-2012 Pacific College
1004 2 4 04-dec-2012 17-feb-2013 Pacific
1004 3 10 11-oct-2012 31-oct-2012 Atlantic
1005 1 4 27-oct-2012 10-jan-2013 La Jolla
1005 2 1 19-sep-2012 29-oct-2012 Pacific
1006 1 7 29-jan-2012 09-mar-2012 Pacific
1006 2 1 07-jan-2012 16-feb-2012 College
1006 3 Pacific College
1007 1 1 26-oct-2012 05-dec-2012 Pacific
1007 2 Pacific College
1007 3 6 15-oct-2012 04-nov-2012 La Jolla
1008 1 4 23-oct-2012 06-jan-2013 College
1008 2 3 15-oct-2012 24-nov-2012 Pacific
1009 1 1 20-nov-2012 Pacific Pacific
1009 2 11 28-sep-2012 12-dec-2012 Pacific
1009 3 7 22-nov-2012 La Jolla College
1010 1 1 01-sep-2012 11-oct-2012 Pacific
1011 1 4 31-jan-2012 15-apr-2012 La Jolla
1011 2 11 20-nov-2012 College La Jolla
1012 1 11 19-nov-2012 Pacific Atlantic
1012 2 3 29-oct-2012 08-dec-2012 Pacific
This is my current SQL command (not the one I got from Gordon Linoff's comment--that one gave me 2-3 extra rows)
select litwork.btitle,
count(distinct bookcopy.copy_num),
count(distinct request.rdate)
from litwork,
bookcopy,
request
where litwork.lit_id=request.lit_id and
bookcopy.persidh=request.persid
group by btitle;
And that gives me this table (which you can see I have all the correct amount of rows [when you take out the duplicates] but the count numbers are wrong)
BTITLE COUNT(DISTINCTBOOKCOPY.COPY_NUM) COUNT(DISTINCTREQUEST.RDATE)
--------------- -------------------------------- ----------------------------
Linux 1 1
MyApps 2 1
Nature 1 1
The Trojans 3 2
True Java 1 1
The following should work with Oracle's SQL *Plus:
select litwork.btitle, count(distinct bookcopy.copy_num), count(distinct request.rdate)
from litwork, bookcopy, request
where litwork.lit_id = request.lit_id and request.lit_id = bookcopy.lit_id(+)
group by litwork.btitle;
For more info on joins see Oracle SQL*Plus Pocket Reference, 2nd Edition.
Possible solutions to count issue:
Change count(distinct request.rdate) to count(distinct request.PERSID).
Change count(distinct request.rdate) to count(distinct request.*).
Change count(distinct request.rdate) to sum(case when request.rdate is null then 0 else 1 end)
Instead of joining the request table you could join (select lit_id, count(*) as requestCount from request group by lit_id) then select requestCount.
This is probably the best I can do since I do not have the detailed definition of the fields and how they relate. It would also help if I had the expected results and SQL *Plus to test it with.