Advance mysql query with order by - sql-order-by

I use 2 tables to combine data to become like shown as below
SELECT name, price, MIN(price) AS minprice
FROM c, cp
WHERE c.id = cp.id
GROUP BY id
ORDER BY minprice = 0, minprice ASC
For Example:
id name price
1 apple 0
1 green apple 20
2 orange 10
3 strawberry 0
As the data result above the minprice of the group 1 is 0 But I don't want the min price take zero, but this is incorrenct if I give condition having minprice > 0 cause
I wanna my result become like this
2 orange 10
1 green apple 20
3 strawberry 0
Is it possible?

Here is the answer:
SELECT
(
SELECT name
FROM yourtable
WHERE price = _inner._MIN AND id = _inner.id LIMIT 1
)
AS _NAME,
_inner._MIN
FROM
(
SELECT id, IFNULL(MIN(NULLIF(price, 0)),0) AS _MIN
FROM yourtable
GROUP BY id
)
AS _inner
where yourtable is the name of your table.
MIN(NULLIF(price, 0)) allows you to calculate minimum value while not counting a zero.
IFNULL(<...>,0) here just means, that we need a real zero instead of NULL in result.
LIMIT 1 is on the case if we have an items with the same id and price but with different names. I think, you can freely remove this statement.

Related

looking for Number of Members in each country whose preference game is set to NES

SQL Number of Members in each country whose preference game is set to NES
EXPECTED OUTPUT
COUNT(AUD) COUNT(EUR) COUNT(IND) COUNT(LAO) COUNT(USA) COUNT(ZWE)
3 2 0 0 2 1
Here is the SQL fiddle
http://sqlfiddle.com/#!9/a15ec9f/3
We pivot.
select *
from t
pivot(count(MEMBER_ID) for COUNTRY_ID in('AU' as "count(AU)", 'US' as "count(US)", 'LAO' as "count(LAO)", 'IND' as "count(IND)", 'DE' as "count(DE)", 'ZW' as "count(ZW)")) p
count(AU)
count(US)
count(LAO)
count(IND)
count(DE)
count(ZW)
3
7
0
0
4
2
Fiddle
SELECT Member.MemberID, COUNTRY, GAME_TYPE
FROM MEMBER_TABLE
INNER JOIN COUNTRY_TABLE ON Member.COUNTRY_ID= COUNTRY_TABLE.COUNTRY_ID
WHERE Member.GAME_TYPE= 'NES';

Group by on Key columns and get the records having one valid value and zero value

we have a scenario where as per group by key columns i have to get only record having combination of 0 & any valid number for column "ID"
with the below example
TransId,CustomerNm,Date ,Number,Gender,ID
1 ,Surya ,2020-01-01,123456,M ,1234
1 ,Surya ,2020-01-01,123456,M ,0
2 ,Naren ,2020-01-20,123456,M ,3456
2 ,Naren ,2020-01-20,123456,M ,6789
When i try with the below query (key columns: TransId,CustomerNm,Date,Number,Gender)
select TransId,CustomerNm,Date,Number,Gender from INS.Transaction
group by TransId,CustomerNm,Date,Number,Gender having count(*) > 1
i will get both the records
1 ,Surya ,2020-01-01,123456,M
2 ,Naren ,2020-01-20,123456,M
but i am trying to get the records having ID =0 . Expecting output as
1 ,Surya ,2020-01-01,123456,M
Pls suggest if i can add any change in the above query
while doing group by add MIN(ID) in select query and then fetch id 0
select * from (
select TransId,CustomerNm,Date,Number,Gender,MIN(ID) ID from INS.Transaction
group by TransId,CustomerNm,Date,Number,Gender having count(*) > 1 ) where ID = 0
Just add another AND to the having clause to check if min(id) = 0 . I have renamed some columns.
select transid,customernm,transaction_date,some_number,gender
from transaction
group by transid,customernm,transaction_date,some_number,gender
having count(*) > 1 and min(id) = 0;
Note:- Do not use reserved words as column name like date and number

Oracle Select Query on Same Table (self join)

It seems to simple, but not getting desired results
I have a table with there data
Team_id, Player_id, Player_name Game_cd
1 100 abc 24
1 1000 xyz 24
1 588 ert 24
1 500 you 24
2 600 ops 24
2 700 dps 24
2 900 lmv 24
2 200 hmv 24
I have to write a query to get a result like this
Home_team home_plr_id home_player away_team away_plr_id away_player
1 100 abc 2 600 ops
1 1000 xyz 2 900 lmv
The query I wrote
select f1.Team_id as home_team,
f1.player_id as home_plr_id,
f1.player_Name as home_player,
f2.Team_id as away_team,
f2.player_id as away_plr_id,
f2.player_Name as home_player
from game f1, game f2
where
f1.team_id<> f2.team_id and
f1.game_cd = f2.game_cd
Alternative to #Radagast81's self-join is pivot, available in your Oracle version:
select home_plr_id, home_plr_name, away_plr_id, away_plr_name
from (select game.*,
row_number() over (partition by team_id order by player_id) rn
from game)
pivot (max(player_id) plr_id, max(player_name) plr_name
for team_id in (1 home, 2 away))
SQL Fiddle
Players have to be numbered somehow (here by ID), it can be done by name, null or even random. This numbering is needed only to put them in same rows. Pivot works also if numbers of players in teams differs.
It is not clear how you want to pair a home player with an away player. But provided that you don't care about that, the following might be what you are looking for:
WITH game_p AS (SELECT team_id, player_id, player_name, game_cd
, ROW_NUMBER() over (PARTITION BY team_id, game_cd ORDER BY player_id) pos
, dense_rank() over (PARTITION BY game_cd ORDER BY team_id) team_pos
FROM game)
SELECT NVL(f1.game_cd, f2.game_cd) AS game_cd
, f1.Team_id as home_team
, f1.player_id as home_plr_id
, f1.player_Name as home_player
, f2.Team_id as away_team
, f2.player_id as away_plr_id
, f2.player_Name as away_player
FROM (SELECT * FROM game_p WHERE team_pos = 1) f1
FULL JOIN (SELECT * FROM game_p WHERE team_pos = 2) f2
ON f1.game_cd = f2.game_cd
AND f1.pos = f2.pos
The new column POS gives any player of each team a position to pair them with the other team.
The new column TEAM_POS is to get the team_id mapped to the values 1 and 2, as the team_id's can differ per game.
Finally do a FULL JOIN to get the final list. If the number of players are allways the same for both teams you can do a normal join instead...

SQL sample groups

I have a sqlite database that I can read as:
In [42]: df = pd.read_sql("SELECT * FROM all_vs_all", engine)
In [43]:
In [43]: df.head()
Out[43]:
user_data user_model \
0 037d05edbbf8ebaf0eca#172.16.199.165 037d05edbbf8ebaf0eca#172.16.199.165
1 037d05edbbf8ebaf0eca#172.16.199.165 060210bf327a3e3b4621#172.16.199.33
2 037d05edbbf8ebaf0eca#172.16.199.165 1141259bd36ba65bef02#172.21.44.180
3 037d05edbbf8ebaf0eca#172.16.199.165 209627747e2af1f6389e#172.16.199.181
4 037d05edbbf8ebaf0eca#172.16.199.165 303a1aff4ab6e3be82ab#172.21.112.182
score Class time_secs model_name bin_id
0 0.283141 0 1514764800 Flow 0
1 0.999300 1 1514764800 Flow 0
2 1.000000 1 1514764800 Flow 0
3 0.206360 1 1514764800 Flow 0
4 1.000000 1 1514764800 Flow 0
As the table is too big I rather than reading the full table I select a random subset of rows:
This can be done very quckly as:
random_query = "SELECT * FROM all_vs_all WHERE abs(CAST(random() AS REAL))/9223372036854775808 < %f AND %s" % (ratio, time_condition)
df = pd.read_sql(random_query, engine)
The problem is that for each triplet [user_data, user_model, time_secs] I want to get all the rows containing that triplet. Each triplet appears 1 or 2 times.
A possible way to do it is to firstly sample a random set of triplets and then get all the rows that have one of the selected triplets but this seems to be too slow.
Is there an efficient way to do it?
EDIT: If I could load all the data in pandas I would have done something like:
selected_groups = []
for group in df.groupby(['user_data', 'user_model', 'time_secs']):
if np.random.uniform(0,1) > ratio:
selected_groups.append(group)
res = pd.concat(selected_groups)
Few sample join and sql query:
currently admitted :
Select p.patient_no, p.pat_name,p.date_admitted,r.room_extension,p.date_discharged FROM Patient p JOIN room r ON p.room_location = r.room_location where p.date_discharged IS NULL ORDER BY p.patient_no,p.pat_name,p.date_admitted,r.room_extension,p.date_discharged;
vacant rooms:
SELECT r.room_location, r.room_accomadation, r.room_extension FROM room r where r.room_location NOT IN (Select p.room_location FROM patient.p where p.date_discharged IS NULL) ORDER BY r.room_location, r.room_accomadation, r.room_extension;
no charges yet :
SELECT p.patient_no, p.pat_name, COALESCE (b.charge,0.00) charge FROM patient p LEFT JOIN billed b on p.patient_no = b.patient_no WHERE p.patient_no NOT IN (SELECT patient_no FROM billed) group by p.patient_no ORDER BY p.patient_no, p.pat_name,charge;
max salarised :
SELECT phy_id,phy_name, salary FROM physician where salary in (SELECT MAX(salary) FROM physician) UNION
SELECT phy_id,phy_name, salary FROM physician where salary in (SELECT MIN(salary) FROM physician) ORDER BY phy_id,phy_name, salary;
various item consumed by:
select p.pat_name, i.discription, count (i.item code) as item code from patient p join billed b on p.patient no = b. patient no join item i on b.item code = i.item code group by p.patient no, i.item code order by..
patient not receivede treatment:
SELECT p.patient_no,p.pat_name FROM patient p where p.patient_no NOT IN (SELECT t.patient_no FROM treats t)
ORDER BY p.patient_no,p.pat_name;
2 high paid :
Select phy_id, phy_name, date_of_joining, max(salary) as salary from physician group by salary having salary IN (Select salary from physician)
Order by phy_id, phy_name, date_of_joining, salary limit 2;
over 200:
select patient_no, sum (charge), as total charge from billed group by patient no having total charges > 200 order by patient no, total charges

How to select two max value from different records that has same ID for every records in table

i have problem with this case, i have log table that has many same ID with diferent condition. i want to select two max condition from this. i've tried but it just show one record only, not every record in table.
Here's my records table:
order_id seq status____________________
1256 2 4
1256 1 2
1257 0 2
1257 3 1
Here my code:
WITH t AS(
SELECT x.order_id
,MAX(y.seq) AS seq2
,MAX(y.extern_order_status) AS status
FROM t_order_demand x
JOIN t_order_log y
ON x.order_id = y.order_id
where x.order_id like '%12%'
GROUP BY x.order_id)
SELECT *
FROM t
WHERE (t.seq2 || t.status) IN (SELECT MAX(tt.seq2 || tt.status) FROM t tt);
this query works, but sometime it gave wrong value or just show some records, not every records.
i want the result is like this:
order_id seq2 status____________________
1256 2 4
1257 3 2
I think you just want an aggregation:
select d.order_id, max(l.seq2) as seq2, max(l.status) as status
from t_order_demand d join
t_order_log l
on d.order_id = l.order_id
where d.order_id like '%12%'
group by d.order_id;
I'm not sure what your final where clause is supposed to do, but it appears to do unnecessary filtering, compared to what you want.

Resources