How to equiry data using sql when facing condition? - mysql

type cost
A 10
A 11
A 12
B 10
B 10
I have this small sample table. I want to select data where the cost of the same type is different.So the expected outcome should be:
type cost
A 10
A 11
A 12
The cost for A is different so I need to select these "A" out.
So what is the "select" sentence?
Thanks for the replies. Actually my table is little more complex like this
type cost people
A 10 jack
A 11 frank
A 12 lucy
B 10 amy
B 10 tom
I need to select the data meet one of the requirements below:
Same type with different cost
Same type with people "amy"
So the outcome should be like :
type cost people
A 10 jack
A 11 frank
A 12 lucy
B 10 amy
B 10 tom
Select all of type A because the cost is different
Select all of type B because the people has "amy"
I have firgure out how to select for amy like this:
select type, cost, people
from table
where type in
(select type from table where people = 'amy')
I don't know how to combine these conditions.
SQL Fiddle

You can use EXISTS to look for another row with same type but other cost:
select t1.type, t1.cost
from tablename t1
where exists (select * from tablename t2
where t2.type = t1.type
and t2.cost <> t1.cost)
Or have a sub-query that returns type values having different costs, and join with that result:
select t1.type, t1.cost
from tablename t1
join (select type
from tablename
group by type
having max(cost) <> min(cost)) t2
on t1.type = t2.type

Another way is:
select
t.type, t.cost
from t
left join t t1 on t.type = t1.type
and (t.cost <> t1.cost or t1.people = 'amy')
where
not t1.cost is null
group by
t.type, t.cost;
[SQL Fiddle Demo]
Or also:
select *
from t
where exists (
select 1
from t t1
where t1.type = t.type
group by t1.type
having count(distinct t1.cost) > 1
-- below code added your new criteria
union all
select 1
from t t2
where t2.people = 'amy'
);
[SQL Fiddle Demo]

Related

How to return duplicates within a table that share the same value within another column in MySQL?

How would I return the ProductNumbers where the Number is duplicated when it has the same year ?
This is all within the same table.
in this example below, I would expect ProductNumber 123 and 456 to be returned.
Explain reasoning if possible, thank you!
ProductNumber Numb Year
123 45 1
456 45 1
789 45 2
109 54 2
Here's one option using exists:
select *
from yourtable t
where exists (
select 1
from yourtable t2
where t.productnumber != t2.productnumber
and t.numb = t2.numb
and t.year = t2.year
)
Using exists, we check to see if there are other records in the same table whose productnumber is different, but have the same numb and year values.
You can use EXISTS() :
SELECT *
FROM Table T1
WHERE EXISTS
(
SELECT 1
FROM
(SELECT Numb ,Year
FROM Table
GROUP BY Numb
,Year
HAVING COUNT(1)>1
) T2
WHERE T1.Numb = T2.Tumb
AND T1.Year = T2.Year
)
You can also use INNER JOIN
SELECT t1.ProductNumber
FROM Products t1
INNER JOIN Products as t2
ON t1.ProductNumber != t2.ProductNumber
AND t1.Numb = t2.Numb
AND t1.Year = t2.Year

Mysql - Calculate rank grouped by two columns

I have a mysql table like so:
Tbl
[Username Number Type]
manos 5 A
manos 6 B
maria 2 A
maria 3 B
maria 1 C
nick 7 A
nick 4 C
aaron 8 A
I want to create a view where I will have the ranks of each user (by larger Number), grouped by Type, in comparison to the other users in each Type. More specifically, I would like the output to be:
[Username Rank Type]
manos 3 A
manos 1 B
maria 4 A
maria 2 B
maria 2 C
nick 2 A
nick 1 C
aaron 1 A
I have tried the following:
select Username, count(*) as Rank, Type
from Tbl as aw
where
Number <= (
select Number
from Tbl
where Type = aw.Type
)
group by Username, Type
The result is that I get the Subquery returns more than 1 row error.
Any help would be appreciated!
Edit: changed the names of columns as suggested. Also a fiddle to help: http://sqlfiddle.com/#!9/55ec3f
Edit 2: Some clarification and corrections to the "all combinations rank".
Lets say we have another table called Teams:
Teams
[Username Team]
manos T1
manos T2
maria T1
maria T2
nick T1
nick T2
aaron T3
In this case I want to extract ranks on each combination of group(s) and Types, i.e. for Manos I would like:
Rank against people in T1 with type A
Rank against people in T2 with type A
Rank against people in T1 with type B
Rank against people in T2 with type B
Rank against people in T1 AND T2 with type A
Rank against people in T1 AND T2 with type B
For the sake of sanity, I renamed your group column...
SELECT username
, user_group
, number
, CASE WHEN #prev=user_group THEN #i:=#i+1 ELSE #i:=1 END rank
, #prev:=user_group
FROM my_table x
, (SELECT #prev:=null, #i:=0) vars
ORDER
BY user_group
, number DESC;
Correct code:
select Username, (select Number
from Tbl as t
where t.Type = aw.Type and t.Username = aw.Username) as Rank, Type from Tbl as aw where
Number <= (
select Number
from Tbl as t
where t.Type = aw.Type and t.Username = aw.Username
) group by Username, Type

Using a nested query to get details of two tables

TABLE 1 TABLE 2
id name mob id course mark
1 joe 0000 1 English 77
2 john 0000 2 maths 89
I need to show the name of the person from table 1 who has the MAX(grade) in table 2 using a nested query.
SELECT t1.name
FROM t1
WHERE t1.id = t2.id = (
SELECT id
FROM t2
WHERE mark =
(
SELECT MAX(mark)
FROM t2
)
);
Well, this satisfies the brief ;-):
SELECT a.*
FROM table_a a
JOIN (SELECT * FROM table_b) b
ON b.id = a.id
ORDER
BY mark DESC
LIMIT 1;

Group dates based on variable periods

i have two tables as follows------
table-1
CalenderType periodNumber periodstartdate
1 1 01-01-2013
1 2 11-01-2013
1 3 15-01-2013
1 4 25-01-2013
2 1 01-01-2013
2 2 15-01-2013
2 3 20-01-2013
2 4 25-01-2013
table2
Incidents Date
xyz 02-01-2013
xxyyzz 03-01-2013
ccvvb 12-01-2013
vvfg 16-01-2013
x3 17-01-2013
x5 24-01-2013
Now i want to find out the number of incidents took place in a given period(the Calendar type may change on runtime like)
the query should look something like this
select .......
from ......
where CalendarType=1
which should return
CalendarType PeriodNumber Incidents
1 1 2
1 2 1
1 3 3
1 4 0
can someone suggest me an approach or any method how this can be achieved.
Note:each period is variable in size.peroid1 may have 10 days period2 may have 5 days etc.
I think this does what you want, although I don't understand how you arrived at your sample output:
select t.CalenderType, t.periodNumber, count(*) as Incidents
from Table1 t
inner join (
select t2.Date, t2.Incidents, max(t1.periodstartdate) as PeriodStartDate
from Table2 t2
inner join Table1 t1 on t2.Date >= t1.periodstartdate
where CalenderType = 1
group by t2.Date, t2.Incidents
) a on t.periodstartdate = a.PeriodStartDate
where CalenderType=1
group by t.CalenderType, t.periodNumber
SQL Fiddle Example
Try this, a bit more general solution,SQLFiddle (Thanks RedFilter for schema):
SELECT t1.CalenderType, t1.periodNumber, count(Incidents)
FROM Table1 t1, Table1 t11, Table2
WHERE
(
(
t1.CalenderType = t11.CalenderType
AND t1.periodNumber = t11.periodNumber - 1
AND Date BETWEEN t1.periodstartdate AND t11.periodstartdate
)
OR
(
t1.periodNumber = (SELECT MAX(periodNumber) FROM Table1 WHERE t1.CalenderType = CalenderType)
AND Date > t1.periodstartdate
)
)
GROUP BY t1.CalenderType, t1.periodNumber
ORDER BY t1.CalenderType, t1.periodNumber

SQL Update query with group by clause

Name type Age
-------------------------------
Vijay 1 23
Kumar 2 26
Anand 3 29
Raju 2 23
Babu 1 21
Muthu 3 27
--------------------------------------
Write a query to update the name of maximum age person in each type into 'HIGH'.
And also please tell me, why the following query is not working
update table1 set name='HIGH' having age = max(age) group by type;
I have changed the script from Derek and it works for me now:
UPDATE table1 AS t
INNER JOIN
(SELECT type,max(age) mage FROM table1 GROUP BY type) t1
ON t.type = t1.type AND t.age = t1.mage
SET name='HIGH'
You can't use group by directly in an update statement. It'll have to look more like this:
update t
set name='HIGH'
from table1 t
inner join (select type,max(age) mage from table1 group by type) t1
on t.type = t1.type and t.age = t1.mage;
Since I looked-up this response and found it a little bit confusing to read, I experimented to confirm that the following query does work, confirming Svetlana's highly-upvoted original post:
update archives_forum f
inner join ( select forum_id,
min(earliest_post) as earliest,
max(earliest_post) as latest
from archives_topic
group by forum_id
) t
on (t.forum_id = f.id)
set f.earliest_post = t.earliest, f.latest_post = t.latest;
Now you know ... and so do I.
You can use a semi-join:
SQL> UPDATE table1 t_outer
2 SET NAME = 'HIGH'
3 WHERE age >= ALL (SELECT age
4 FROM table1 t_inner
5 WHERE t_inner.type = t_outer.type);
3 rows updated
SQL> select * from table1;
NAME TYPE AGE
---------- ---------- ----------
HIGH 1 23
HIGH 2 26
HIGH 3 29
Raju 2 23
Babu 1 21
Muthu 3 27
6 rows selected
Your query won't work because you can't compare an aggregate and a column value directly in a group by query. Furthermore you can't update an aggregate.
try this
update table1 set name='HIGH' having age in(select max(age) from table1 group by type);
you can use the below code.
Update table1#
inner Join (Select max(age) as age, type from Table1 group by Table1) t ON table.age = t.age#
Set name = 'High'#
update table1 set Name='HIGH' where Age in(select max(Age) from table1)
UPDATE table1 SET name = 'HIGH' WHERE age IN (SELECT MAX(age) FROM table1 GROUP BY name)
You cannot use a GroupBy clause for an Update Statement. You will have to use a sub query during that time
Update table1
Set name = 'High'
From table1
Join (Select max(age), type from Table1 group by Table1) t ON table1.age = t.age