Creating a query that converts "chained" ids to "grouped" ids - mysql

I request anyone to help me title this question better, I am unsure on how to call it. Perhaps someone will have an idea after they read the question below:
So I have a set of players and their groups stored in MySQL. In the DB, due to legacy reasons they are stored in a strange manner (like a chain), as shown below:
Player_Id New_Group
100 1
101 0
102 0
103 0
104 1
105 0
106 0
107 0
108 0
So here basically PlayerId 100 has New_Group set as 1. So he is at the start of a new group. Now all the players after him since they have New_Group as 0, fall into his group. When we get to 104, a new group starts.
What I want to do is to write a query which will give result like so:
Player_Id Group_Id
100 1
101 1
102 1
103 1
104 2
105 2
106 2
107 2
108 2
You get the idea...I am trying to convert the New_Group logic into something that just generates pseudo-group-Ids for the players.
However it is beyond my SQL skills to do this. If any SQL Guru can help me that would be AWESOME. I use MySQL.

How's this?
SET #group = 0;
SELECT Player_Id, IF(New_Group, #group:=#group + 1, #group) AS Group_Id
FROM [table]
ORDER BY Player_Id;

SELECT player_id
, CASE WHEN new_group = 1 THEN #i:=#i+1 ELSE #i:=#i END i
FROM my_table
, (SELECT #i:=0) vars
ORDER
BY player_id;

Assuming you have some column in the table that is ascending you could do:
select Player_Id, count(select * from [table] t2 where new_group=1 and t2.ascending_row <= t1.ascending_row) from [table] t1
In your example above Player_Id could be used for ascending_row as the values are all incrementing. If not you may need to create a temporary table with a column containing the row id and then use that.

Related

Count ID in sql query

I have the following data,
id emp_id csa_taken
1 100 2
2 100 2
3 100 0
4 100 2
5 101 2
6 101 2
7 101 0
8 101 0
I expect a result with count where csa_taken=2 for individual employee.
expected result:
emp_id count_csa_taken
100 3
101 2
I have tried the following query with a failed attempt.
Select count(employee_id) From $employeeCSA where csa_taken=2
Please suggest as I am new to sql.
If I understand you correctly you like to count all employees with a cas_taken of two. As there are multiple entries for the csa_taken for one employee you need to group them.
E.g.:
SELECT COUNT(*) FROM $employeeCSA WHERE csa_taken = 2 GROUP_BY employee_id
Please note that COUNT(*) counts the rows (not the fields).
You also need group by. Try like:
Select count(employee_id),emp_id From $employeeCSA where csa_taken=2
group by emp_id
If i understand correctly, then you can try this:
SELECT emp_id,COUNT(emp_id) from dbo.Sample WHERE csa_token = 2 GROUP BY emp_id

Sql select where a column has been set atleast once

I have this table
**applications**
id user_id company_id shortlisted
1 10 99 0
2 10 100 1
3 10 101 1
4 10 102 0
5 11 99 1
6 12 99 0
6 12 101 0
What I want is to select all users
which have been shortlisted at-least once
which have not been shortlisted at all
For the first case, i have the following query:
SELECT user_id
from applications
where shortlisted=1
Group
By user_id
and this gives me the expected result like below
**applications**
user_id
10
11
But I'm trying the following query for the second case and it returns me an empty set:
Select user_id
from applications as Application
where shortlisted=0
and NOT EXISTS(Select user_id from applications where user_id=Application.user_id and shortlisted=1)
What am i missing?
PS: Please ignore any typos as i typed them manually for this post.
To get both results in a single query simply use aggregation:
select user_id, max(shortlisted) as was_shortlisted
from applications
group By user_id
You can use group by and having for both.
For the first:
select user_id
from applications
group By user_id
having max(shortlisted) = 1;
For the second:
select user_id
from applications
group By user_id
having max(shortlisted) = 0;
In all honesty, your version with the where is more efficient for the first query. This is just to show how closely related the queries are.
You can try following query;
select user_id from table1
group by user_id having MIN(shortlisted) = 1
This will give you to at least have shortlisted = 1 condition and don't have shortlisted = 0 records.

Update particular value in table column mysql

I have table like this:
id business_id path photo
1 11 1.jpg 0
2 11 2.jpg 0
3 15 1.jpg 0
4 15 3.jpg 0
5 15 4.jpg 0
6 21 scan1.jpg 0
7 21 scan2.jpg 0
8 22 1.jpg 1
....
I want to update table so that for each business lets say in above scenario for business 11. one of the path should have photo set to 1.
If photo is already set to 1 (like for business_id = 22) above it should not change that.
I think below query will work for 1 business_id at a time:
Update business
set photo = 1
where id = 11 limit 1
But my question is how can I run this in a batch? So I can update all at once.
You can update your table by using below query,It will get the maximum for each business_id which has all photos set to 0 and using join you sub select will update a single record per business_id to photo = 1
update business b
join (select max(id) id, business_id
from business
group by business_id
having sum(photo = 0) = count(*)) t
on(b.id = t.id)
set b.photo = 1
DEMO
You could try this query:
UPDATE business SET photo = 1 WHERE id IN
(SELECT MIN(id) , MAX(photo) FROM business
GROUP BY business_id HAVING max(photo) = 0)
Additional info: The next query gives you a list of rows where business doesn't have any photo. This query was the initial point for my answer.
SELECT business_id , MAX(photo) FROM business
GROUP BY business_id HAVING max(photo) = 0

Mysql multiple distinct wont work

I have tried this multiple distinct from MySQL and I cant seem to get anything to work... I have a table that is a history table. The appartments can be found many times from the same building with different status. I need to find the newest one for each appartment (the one with the highest id ORDER BY id)
id building appartment_id status
208 1 2 2
209 1 3 2
210 1 4 2
211 1 5 2
212 1 6 2
213 1 7 2
214 1 2 1
215 1 2 3
But how do I do that?! :S
I have tried this:
SELECT *, GROUP_CONCAT(appartment_id, building)
FROM `ib30_history`
group by appartment_id, building
order by id DESC
It seems to work but im not sure that is the right way of doing it and the code that uses the output seems to make funny things running through the data so im not sure it really works!
SELECT yourtable.id, yourtable.building, yourtable.appartment_id, yourtable.status
FROM yourtable
INNER JOIN (
SELECT MAX(id) AS id
FROM yourtable
GROUP BY building, appartment_id
) AS child ON yourtable.id = child.id
Get rid of distinct and use something like:
GROUP BY building , appartment_id
What you're looking for is called GROUP BY, and MySQL's documentation knows a lot about how it's to be used. At the timeI type this, the OP doesn't contain a query so I cannot give you an example...
SELECT a.*
FROM table_name a
INNER JOIN
(SELECT MAX(id) as max_id
FROM table_name
GROUP BY appartment_id) b
ON (b.max_id = a.id)

Using join in place of this sub-query in MySQL

I have a table by the following structure and records, All i want to do is to just extract orderid of those records whose status id is either 1 or 2 , i want to exclude all orderid with statusid=3 , , problem is that orderid 106 has both status 1 and 3 ...
I have written a sub-query which serves the purpose..
select *
from orders_status_history
where orders_id NOT IN
(select orders_id
from orders_status_history
where orders_status_id = 3)
is there any other way of doing this without using sub-queries as i have heard it hampers performance. As my query can return thousands of rows as well.
id order-id status-id
1 1 1
2 2 1
3 105 1
4 106 1
5 106 3
6 108 1
7 109 1
8 109 2
Any help or suggestion will be highly appreciated ..Thanks in advance..
You may do that:
SELECT osh.*
FROM orders_status_history osh
LEFT JOIN
orders_status_history oshd
ON oshd.orders_id = osh_orders_id
AND oshd.orders_status_id = 3
WHERE oshd.orders_id IS NULL
However, if you have an index on order_status_history (orders_id, orders_status_id), then the NOT IN query is just as fine.
You may want to read this:
NOT IN vs. NOT EXISTS vs. LEFT JOIN / IS NULL: MySQL
I wonder why you use sub query while you can use the following query
select orders_id from orders_status_history where orders_status_id <> 3
Please try this , and I hope it helps