Case with multiple records - mysql

I have a data set which looks like this:
id No_trans Bank
1 2 VISA
1 1 PAYPAL
2 3 MASTERCARD
3 1 MASTERCARD
3 4 PAYPAL
4 1 PAYPAL
What I need to do is if id has PAYPAL, change it to another bank, for example.
For id = 1, PAYPAL should be as VISA, but for id = 3, it should be MASTERCARD, however, for id = 4, it should be PAYPAL because it doesn't have another Bank record.
select id ,count(No_trans) ,
case Bank when PAYPAL then VISA
when PAYPAL then MASTERCARD
else
PAYPAL
end as bank
from table
Grouping by 1 and 3
is not going to work, because I need to change it depending on which other record has the same id bank.
If this ID has a bank different from PAYPAL, use it for other records with the same ID, if not, use it as it is.
create temporary table t1
(
ID INT
, no_trans int
, bank varchar (255)
);
INSERT INTO t1 values
(1, 2 , 'VISA'),
(1 , 1 , 'PAYPAL'),
(2, 3 , 'MASTERCARD'),
(3 , 1 , 'MASTERCARD'),
(3, 4 , 'PAYPAL'),
(4 , 1 , 'PAYPAL');
select * from t1
where id = 1
return
'1','2','VISA'
'1','1','PAYPAL'
I need
'1','2','VISA'
'1','1','VISA'
for
select * from t1
where id = 3
should be
ID, no_trans, bank
3, 1, MASTERCARD
3, 4, MASTERCARD
for
select * from t1
where id = 4
ID, no_trans, bank
4, 1, PAYPAL

You can use aggregation:
select id,
coalesce(max(case when Bank <> 'PayPal' then Bank end),
max(Bank)
)
from t
group by id;
If you want the original rows, then perhaps a subquery is simpler:
select t.*,
(select t2.bank
from t t2
where t2.id = t.id
order by (t2.bank <> 'PayPal) desc
limit 1
) as new_bank
from t;

Try the following:
select
ID,
no_trans,
If (id = 1 and bank = 'PAYPAL', 'VISA',bank)as bank
from t1
where id = 1
For Id = 3
select
ID,
no_trans,
If (id = 3 and bank = 'PAYPAL', 'MATERCARD',bank) as bank
from t1
where id = 3;
If you need all of them combined:
select
ID,
no_trans,
If (bank = 'PAYPAL',If(id = 1,'VISA',If(id=3,'MASTERCARD',bank)),bank) as bank
from t1;
SQLFIDDLE DEMO

Related

MySQL Query for subtracting values from 2 tables

Hello I have this tables
Table A
ID Name Price QTY
1 name1 1000 10
2 name2 1200 5
Table B
ID Name Price QTY
1 name1 1000 2
I want to achieve
Table C
ID Name Price QTY
1 name1 1000 8
2 name2 1200 5
With my query SELECT DISTINCT ta.name, ta.price,(ta.quantity - tb.quantity) AS quantity, FROM TableA AS ta INNER JOIN TableB AS tb ON ta.id = tb.id
What I get is this
Table C
ID Name Price QTY
1 name1 1000 8
2 name2 1200 3
I sorry I really cant think of a way how to achieve what I want. Thanks for your help.
Your query actually gets you one line instead of two:
-- result set
# name, price, quantity
name1, 1000, 8
Based on your expected output,we can use:
SELECT ta.ID, ta.name, ta.price, ifnull((ta.QTY - tb.QTY),ta.QTY) AS quantity
FROM TableA AS ta
LEFT JOIN TableB AS tb
ON ta.name = tb.name and ta.price=tb.price;
-- result set:
# ID, name, price, quantity
1, name1, 1000, 8
2, name2, 1200, 5
This is the last updated answer I can give you for you updated request.Please consider firing a new question if it does not fulfill.
-- Supposing your latest tables have the following data.
insert TableA values
(1 , 'name1' , 1000 , 10)
,(2 , 'name2' , 1200 , 5);
insert TableB values
(1 , 'name1' , 1000 , 2),
(2 , 'name2', 1000 , 3)
;
-- You probably want this:
SELECT ta.ID, ta.name, ta.price, ifnull((ta.QTY - tb.QTY),ta.QTY) AS quantity
FROM TableA AS ta
LEFT JOIN TableB AS tb
ON ta.name = tb.name and ta.price=tb.price
union
SELECT Id , name , price , QTY
from TableB t
where not exists (select * from TableA where t.name=name and t.price=price)
;
-- result set:
# ID, name, price, quantity
1, name1, 1000, 8
2, name2, 1200, 5
2, name2, 1000, 3

select from same value mysql 5.7

i have 2 tables, this is my fiddle https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=7009f83d39d688e38aceb781b7fdc903
CREATE TABLE users (
ID int(10) PRIMARY KEY NOT NULL,
email varchar(255));
CREATE TABLE order_match_detail (ID int(10) PRIMARY KEY NOT NULL,
createdBy int(11),
price decimal(10,2));
INSERT INTO users(ID, email)
SELECT 1, 'testing1#gmail.com' UNION ALL
SELECT 2, 'testing2#gmail.com' UNION ALL
SELECT 3, 'testing3#gmail.com' UNION ALL
SELECT 4, 'testing1#gmail.com' UNION ALL
SELECT 5, 'testing3#gmail.com';
INSERT INTO order_match_detail (ID, createdby, price)
SELECT 1, 1, 2000 UNION ALL
SELECT 2, 1, 2000 UNION ALL
SELECT 3, 2, 2000 UNION ALL
SELECT 4, 2, 3000;
select * from users;
select * from order_match_detail;
with users.id = order_match_detail.createdby
i want to find out the users_id where have same email, with this query
SELECT * FROM users INNER JOIN(
SELECT email FROM users GROUP BY email HAVING COUNT(email) > 1 order by email)
temp ON users.email = temp.email;
after i had this query, i want to separate each users_id with same email above where doing transaction, and not doing transaction based on order_match_detail tables, users_id with no transaction are not appear in order_match_detail table. how to separate each users_id become doing transaction and not doing transaction
expected results based on the fiddle
+--------------------------------+-------------------------------+
| users_Id doing transaction | users_id not doing transaction|
+--------------------------------+-------------------------------+
| 1 | 3 |
| | 4 |
| | 5 |
+--------------------------------+-------------------------------+

MySql query to count the score of each user

The query needs to counts the total points for each user. For each qid the user with lower time gets a point and total point is sum of all the points. Below query just returns the total attempts for each user, need a way to return the points.
Incorrect Query=select user, count(*) from (select * from (select * from xyz order by
time ASC) as temp1 group by temp1.user,temp1.qid) AS temp2 group by user
DB:
CREATE TABLE xyz (
id INT PRIMARY KEY AUTO_INCREMENT,
user VARCHAR(20),
time INT,
qid INT
);
INSERT INTO xyz VALUES ( 1 , 'abc' , 15 , 1);
INSERT INTO xyz VALUES ( 2 , 'abc' , 6 , 1);
INSERT INTO xyz VALUES ( 3 , 'xyz' , 11 , 1);
INSERT INTO xyz VALUES ( 4 , 'abc' , 4 , 1);
INSERT INTO xyz VALUES ( 5 , 'xyz' , 13 , 2);
INSERT INTO xyz VALUES ( 6 , 'abc' , 11 ,2);
INSERT INTO xyz VALUES ( 7 , 'abc' , 9 , 3);
INSERT INTO xyz VALUES ( 8 , 'xyz' , 10 , 3);
INSERT INTO xyz VALUES ( 9 , 'xyz' , 2 , 3);
INSERT INTO xyz VALUES ( 10 , 'xyz' , 2 , 4);
Expected output:
USER Score
abc 2
xyz 2
Output Explanation:
For qid=1, abc has lower time so 1 point to abc
For qid=2, abc has lower time so 1 point to abc
For qid=3, xyz has lower time so 1 point to xyz
For qid=4, xyz has lower time so 1 point to xyz
sqlfiddle Link
You need to find the number of times that a user is "first" for each qid. Here is one method:
select xyz.user, count(*) as score
from xyz join
(select qid, min(time) as mintime
from xyz
group by qid
) q
on xyz.qid = q.qid and xyz.time = q.mintime
group by xyz.user;

MySQL: fetching an id from an associative table, with specific associations

I've got the following associative table between packages and products (simplified):
package_id product_id count
1 1 6
1 2 1
1 3 1
2 1 6
2 2 1
3 1 6
4 1 8
4 2 1
I'm trying to work out how to create an query which is able to select specific package_id's which contain exactly the products and their counts I supply. So if I'd be trying to find the package that contains: (product_id = 1 AND count = 6) AND (product_id = 2 AND count = 1), it should only return package_id 2 and not the others, because those contain other products and / or other counts.
I'd be happy to work this out in my code (PHP) instead of SQL, but since I'm trying to get to the bottom of queries, I'd like to know how this is done.
This is called Relational Division
SELECT a.package_ID
FROM tableName a
WHERE (a.product_ID = 1 AND a.count = 6) OR
(a.product_ID = 2 AND a.count = 1)
GROUP BY a.package_ID
HAVING COUNT(*) = 2 AND
COUNT(*) = (SELECT COUNT(*) FROM tableName WHERE package_ID = a.package_ID)
SQLFiddle Demo
OR
SELECT package_ID
FROM tableName
WHERE (product_ID, `count`) in ((1, 6), (2, 1))
GROUP BY package_ID
HAVING COUNT(DISTINCT product_ID, `count`) = 2 AND
COUNT(*) = (SELECT COUNT(*) FROM tableName WHERE package_ID = a.package_ID)
SQLFiddle Demo

Query to get the common values

I have a table like
userId classId
1 1
2 1
3 1
1 2
2 2
1 3
2 4
3 5
In the above, [1, 2, 3] share class 1. [1, 2] share class 2, and so on.
If I give userId 1, 2, 3 in a query that should return classId 1.
If I give 1 and 2, the query should return 2.
If I give 1, the query should return 3.
How can I write a MySQL query for that?
The relational operator you require is division, popularly known as "the supplier who supplies all parts".
Because you don't consider class = 1 to be a valid result when given user = {1, 2}, you should be looking at exact division (i.e. without a remainder). You also need to consider what the result should be given an empty divisor.
This was tested with Postgresql, but I'm pretty sure it should work without much modifications under mysql.
Table setup
drop table classes;
create table classes (
user_id integer,
class_id integer
);
insert into classes values(1, 1);
insert into classes values(2, 1);
insert into classes values(3, 1);
insert into classes values(1, 2);
insert into classes values(2, 2);
insert into classes values(1, 3);
insert into classes values(2, 4);
insert into classes values(3, 5);
1, 2, 3
select max(class_id) from
(
select class_id
from classes
where user_id = 1
intersect
select class_id
from classes
where user_id = 2
intersect
select class_id
from classes
where user_id = 3
) as foo;
1, 2
select max(class_id) from
(
select class_id
from classes
where user_id = 1
intersect
select class_id
from classes
where user_id = 2
) as foo;
1 (Could be simplified, but I prefer it so, for symmetry reasons)
select max(class_id) from
(
select class_id
from classes
where user_id = 1
) as foo;
You could use a query like this (for users 1,2,3) -
SELECT t1.classId FROM (SELECT * FROM users_classes WHERE userId = 1) t1 -- for userId = 1
JOIN (SELECT * FROM users_classes WHERE userId = 2) t2 ON t1.classId = t2.classId -- for userId = 2
JOIN (SELECT * FROM users_classes WHERE userId = 3) t3 ON t1.classId = t3.classId -- for userId = 3
For users 1,2 -
SELECT t1.classId FROM (SELECT * FROM users_classes WHERE userId = 1) t1 -- for userId = 1
JOIN (SELECT * FROM users_classes WHERE userId = 2) t2 ON t1.classId = t2.classId -- for userId = 2
These query will output all possible classId, to get one classId you can add LIMIT or aggregate function.
Try this
SELECT DISTINCT (
classId
)
FROM `data`
WHERE userid =1
OR userid =2 or classid = 3
LIMIT 0 , 1
SELECT DISTINCT (
classId
)
FROM `data`
WHERE userid =1
OR userid =2
LIMIT 1 , 1
SELECT DISTINCT (
classId
)
FROM `data`
WHERE userid =1
LIMIT 2 , 1