I used another table and generated a MySQL views, by using that view I coded the below:
SELECT staffid,
CASE Frequency
WHEN 'Less' THEN COUNT(Frequency)
ELSE '0'
END AS LessCount,
CASE Frequency
WHEN 'Full' THEN COUNT(Frequency)
ELSE '0'
END AS FullCount,
CASE Frequency
WHEN 'More' THEN COUNT(Frequency)
ELSE '0'
END AS MoreCount
FROM effort_frequency
GROUP BY staffid, Frequency
I used the above code to get the below table:
+-------+-----------+-----------+-----------+
| staff | lessCount | FullCount | MoreCount |
+-------+-----------+-----------+-----------+
| 10 | 2 | 0 | 0 |
| 10 | 0 | 1 | 0 |
| 10 | 0 | 0 | 3 |
| 11 | 1 | 0 | 0 |
| 11 | 0 | 3 | 0 |
+-------+-----------+-----------+-----------+
I need this to be converted, which should look like:
+-------+-----------+-----------+-----------+
| staff | lessCount | FullCount | MoreCount |
+-------+-----------+-----------+-----------+
| 10 | 2 | 1 | 3 |
| 11 | 1 | 3 | 0 |
+-------+-----------+-----------+-----------+
How we can do this in MySQL ?
SELECT staffid AS staff,
SUM(Frequency='Less') AS lessCount,
SUM(Frequency='Full') AS FullCount,
SUM(Frequency='More') AS MoreCount
FROM effort_frequency
GROUP BY staffid
Related
I am not sure if it is asked before, but the problem is like this.
+---------+---------------+------+-----------+
| item_id | name | data |priority | expire |
+---------+---------------+------+-----------+
| 11 | decimal_queue | data| 0 | 0 |
+---------+---------------+------+------+----+
Now, There are different type of queue, in the name decimal_queue, single_queue, three_queue, I want to get them one by one in SELECT query with limit of lets;s say 10
So, first let's suppose item of decimal_queue then the next item single_queue then three_queue in this manner, also I want to limit total number to max 10 and the queue can be dynamic in number.
Is it achievable, I am also using PHP in backend, if that also solves to get array like that.
I tested - but not sure is it achievable, if yes - how to approach this
You can use a CTE to create a ROW_NUMBER() window function and create a limit for your rows in a WHERE clause:
WITH cte AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY name ORDER BY name) AS rn
FROM queues)
SELECT
item_id,
name,
data,
priority,
expire
FROM cte
WHERE rn <= 10
ORDER BY rn, name
Result:
| item_id | name | data | priority | expire |
|---------|---------------|------|----------|--------|
| 11 | decimal_queue | data | 0 | 0 |
| 12 | single_queue | data | 2 | 1 |
| 13 | three_queue | data | 0 | 0 |
| 14 | decimal_queue | data | 3 | 0 |
| 16 | single_queue | data | 0 | 0 |
| 15 | three_queue | data | 1 | 1 |
| 17 | decimal_queue | data | 3 | 1 |
| 19 | single_queue | data | 0 | 1 |
| 20 | three_queue | data | 3 | 0 |
| 18 | decimal_queue | data | 2 | 0 |
| 21 | single_queue | data | 0 | 1 |
| 22 | three_queue | data | 2 | 1 |
| 23 | decimal_queue | data | 1 | 0 |
| 24 | single_queue | data | 1 | 0 |
Demo here.
You can also reverse the order (or specify any order you like) by using the FIELD function instead of name in your ORDER BY:
ORDER BY rn, FIELD(name,'three_queue','single_queue','decimal_queue')
Demo here.
I have a table as below:
CREATE TABLE IF NOT EXISTS `room_players`
(`id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY
,`player_id` int(11) NOT NULL
,`room_id` tinyint(1) NOT NULL
,`dealer` tinyint(1) NOT NULL
);
INSERT INTO room_players (`player_id`, `room_id`, `dealer`) VALUES
(1, 1, '0'),
(2, 1, '0'),
(3, 1, '0'),
(4, 1, '1'),
(5, 1, '0');
I need to get row after WHERE dealer='1' AND room_id='1'; in this case, it should return player_id = 5.
Now, when dealer = 1 for player_id = 5, then it should select the first player_id of the current room_id.
I tried:
SELECT *
FROM room_players
WHERE room_id='1'
AND id IN ( SELECT ID+1
FROM room_players
WHERE room_id='1'
AND dealer != 1
)
Selecting the next row works with this query but, when we got to the last player in line, it will return nothing.
I could run 2 different queries to get it work, but I would like to use an eloquent single query.
Using window functions we can achieve this in 1 query pretty easily:
first_value() asending id
first_value() descending id
lead()
case expression to figure out when to display next dealer value.
Just note: elegance of 1 query may make maintenance more complex.
it's not always better to build 1 sometimes two IS simplier.
Demo
you can adjust dealer to wherever you want and it will return the next dealer player number on the dealer number line. you didn't define expected results so I am unsure what you result is to look like.
SELECT *
, case WHEN dealer=1 and player_id = first_value(player_id) over (partition by room_id order by id desc)
THEN first_value(player_id) over (partition by room_id order by id)
WHEN dealer=1
THEN lead(player_id) over (partition by room_id order by id) end as NextDealer
From room_players
Giving us:
+----+-----------+---------+--------+------------+
| id | player_id | room_id | dealer | NextDealer |
+----+-----------+---------+--------+------------+
| 1 | 1 | 1 | 0 | |
| 2 | 2 | 1 | 1 | 3 |
| 3 | 3 | 1 | 0 | |
| 4 | 4 | 1 | 0 | |
| 5 | 5 | 1 | 0 | |
+----+-----------+---------+--------+------------+
or
+----+-----------+---------+--------+------------+
| id | player_id | room_id | dealer | NextDealer |
+----+-----------+---------+--------+------------+
| 1 | 1 | 1 | 0 | |
| 2 | 2 | 1 | 0 | |
| 3 | 3 | 1 | 0 | |
| 4 | 4 | 1 | 0 | |
| 5 | 5 | 1 | 1 | 1 |
+----+-----------+---------+--------+------------+
depending on who is dealer..
DB Fiddle expanded to show what's happening with case expression & show how to get dealer/room. Yes I had to use a CTE because the window functions can't have the data limited; it first must have the data materialized. But, if you create the CTE as a view and you're simply passing in the room to get the next dealer this works fine imo.
We can use:
WITH CTE AS (
SELECT *,
case WHEN dealer=1 and player_id = first_value(player_id) over (partition by room_id order by id desc)
THEN first_value(player_id) over (partition by room_id order by id)
WHEN dealer=1
THEN lead(player_id) over (partition by room_id order by id) end NextDealer
From room_players)
SELECT room_id, NextDealer FROM CTE WHERE NextDealer is not null
to get data by room and next dealer giving us: (I added some additional test data to make sure certain edge cases were working as expected)
+---------+------------+
| room_id | NextDealer |
+---------+------------+
| 1 | 7 |
| 2 | 99 |
+---------+------------+
With Date of:
+----+-----------+---------+--------+
| id | player_id | room_id | dealer |
+----+-----------+---------+--------+
| 1 | 1 | 1 | 0 |
| 2 | 2 | 1 | 0 |
| 3 | 3 | 1 | 0 |
| 4 | 4 | 1 | 1 |
| 5 | 7 | 1 | 0 |
| 6 | 99 | 2 | 0 |
| 7 | 14 | 2 | 0 |
| 8 | 22 | 2 | 0 |
| 9 | 77 | 2 | 1 |
| 10 | 15 | 2 | 0 |
+----+-----------+---------+--------+
I get:
+----+-----------+---------+--------+----+----+----+------------+
| id | player_id | room_id | dealer | a | b | c | NextDealer |
+----+-----------+---------+--------+----+----+----+------------+
| 1 | 1 | 1 | 0 | 7 | 1 | 2 | |
| 2 | 2 | 1 | 0 | 7 | 1 | 3 | |
| 3 | 3 | 1 | 0 | 7 | 1 | 4 | |
| 4 | 4 | 1 | 1 | 7 | 1 | 7 | 7 |
| 5 | 7 | 1 | 0 | 7 | 1 | | |
| 6 | 99 | 2 | 0 | 15 | 99 | 14 | |
| 7 | 14 | 2 | 0 | 15 | 99 | 22 | |
| 8 | 22 | 2 | 0 | 15 | 99 | 77 | |
| 9 | 77 | 2 | 1 | 15 | 99 | 15 | 15 |
| 10 | 15 | 2 | 0 | 15 | 99 | | |
+----+-----------+---------+--------+----+----+----+------------+
I went with slightly different approach, i got to solve it with one simple query, but did some coding with PHP also. Its not the eloquant i wanted, but it works for me.
function dealer($room_id) {
global $con;
$array = array();
$i = 0;
$cd = null;
$query = mysqli_query($con, "SELECT * FROM room_players WHERE room_id='".$room_id."'");
while($ft = mysqli_fetch_array($query)) {
$array[] = array("user_id" => $ft['user_id']);
if($ft['dealer'] == 1) {
$cd = $i;
}
$i++;
}
if(!is_null($cd)) {
if($array[$cd+1]) {
$next = $array[$cd+1];
}else{
$next = $array[0];
}
}else{
$next = $array[array_rand($array, 1)];
}
return $next['user_id'];
}
echo "Next dealer is: ". dealer(1);
I have a table like this
+----+--------+--------+
| id | ref_id | status |
+----+--------+--------+
| 1 | 3 | 1 |
| 2 | 4 | 0 |
| 4 | 6 | 0 |
| 6 | 8 | 1 |
| 8 | 10 | 0 |
| 10 | 12 | 1 |
| 12 | 14 | 1 |
| 14 | 16 | 0 |
| 16 | 18 | 0 |
| 18 | 20 | 0 |
+----+--------+--------+
I want to find the number of rows that has a status 0 in descending order continuously. In this Case number would be 3
+----+--------+--------+
| id | ref_id | status |
+----+--------+--------+
| 1 | 3 | 1 |
| 2 | 4 | 0 |
| 4 | 6 | 0 |
| 6 | 8 | 1 |
| 8 | 10 | 1 |
| 10 | 12 | 1 |
| 12 | 14 | 0 |
| 14 | 16 | 0 |
| 16 | 18 | 0 |
| 18 | 20 | 0 |
+----+--------+--------+
In this case it is four
+----+--------+--------+
| id | ref_id | status |
+----+--------+--------+
| 1 | 3 | 1 |
| 2 | 4 | 0 |
| 4 | 6 | 0 |
| 6 | 8 | 1 |
| 8 | 10 | 1 |
| 10 | 12 | 1 |
| 12 | 14 | 0 |
| 14 | 16 | 0 |
| 16 | 18 | 0 |
| 18 | 20 | 1 |
+----+--------+--------+
In this case it is 0
So far I tried is processing the rows descending and finding it through php condition . Is there any better way to do it ?
I used this code in codeigniter and get the result
$this->db->select('count(id) as number');
$this->db->from('tablename');
$this->db->where('id > (select max(id) FROM tablename where status = 1)',
NULL, FALSE);
In mysql
SELECT count(id) as number FROM tablename
WHERE id > (select max(id) FROM tablename where status = 1)
I have a user and pages table, and these two have many to many relationship between them with the bridge table user privileges. What I want to get all the pages name and only those are marked that is assigned to that user.
want some think like this
+---------+----------------------------------+
| user_id | page_name | Assigned|
+---------+----------------------------------+
| 1 | Add Project | 0 |
| 1 | Department | 0 |
| 1 | Category | 1 |
| 1 | Item | 0 |
| 1 | Units | 1 |
| 1 | Stock In | 0 |
| 1 | Stock Card Report | 1 |
+---------+------------------------+---------|
for now my query is this;
Select up.user_id, p.page_name FROM user_privileges up, pages p where p.page_id = up.page_id and up.user_id = 1;
and it returns this;
+---------+------------------------+
| user_id | page_name |
+---------+------------------------+
| 1 | Add Project |
| 1 | Department |
| 1 | Category |
| 1 | Item |
| 1 | Units |
| 1 | Stock In |
| 1 | Stock Card Report |
+---------+------------------------+
The Scheme is this;
table - user
+---------+-----------+
| user_id | user_name |
+---------+-----------+
| 4 | saif |
| 1 | admin |
| 5 | taqi |
| 2 | rashid |
+---------+-----------+
table - pages
+---------+---------------+
| page_id | page_name |
+---------+---------------+
| 2 | Page 1 |
| 3 | Page 2 |
| 5 | Page 3 |
| 6 | Page 4 |
| 7 | Page 5 |
| 8 | Page 6 |
| 9 | Page 7 |
| 10 | Page 8 |
| 11 | Page 9 |
| 13 | Page 10 |
| 14 | Page 11 |
| 15 | Page 12 |
| 16 | Page 13 |
| 18 | Page 14 |
| 19 | Page 15 |
| 20 | Page 16 |
+---------+---------------+
and table user_privalges for user_id = 1 only.
+--------------------+---------+---------+
| user_privileges_id | user_id | page_id |
+--------------------+---------+---------+
| 1 | 1 | 2 |
| 2 | 1 | 3 |
| 3 | 1 | 5 |
| 4 | 1 | 6 |
| 5 | 1 | 7 |
| 6 | 1 | 8 |
| 7 | 1 | 9 |
| 8 | 1 | 10 |
| 9 | 1 | 11 |
| 10 | 1 | 13 |
| 11 | 1 | 14 |
| 12 | 1 | 15 |
| 13 | 1 | 16 |
| 14 | 1 | 18 |
| 15 | 1 | 19 |
| 16 | 1 | 20 |
+--------------------+---------+---------+
Select up.user_id, p.page_name FROM user_privileges up, pages p where p.page_id = up.page_id and up.user_id = 1 AND up.Assigned=1;
"What I want to get all the pages name and only those are marked that is assigned to that user." So with your edit you should try something like that with case statement
SELECT up.user_id, p.page_name,
CASE
WHEN up.page_id=p.page_id THEN '1'
ELSE '0'
END AS Assigned
FROM pages p left join user_privileges up
ON p.page_id = up.page_id
WHERE up.user_id = 1;
If you are only looking for the user_id = 1 you may do something as
select
1 as user_id,
p.page_name,
case when up.page_id is not null then 1 else 0 end as `Assigned`
from pages p
left join user_privalges up on up.page_id = p.page_id and up.user_id = 1
order by p.page_id
http://www.sqlfiddle.com/#!9/06f65/5
I want to concatenate and count data of the same column, so I can concatenate but I can not count the repeated data.
Here's my table of data:
| ID | bills | class |
|-----|-------|-------|
| 1 | 0.5 | 2 |
| 2 | 1 | 1 |
| 3 | 0.5 | 2 |
| 5 | 1 | 3 |
| 6 | 0 | 2 |
| 7 | 0.5 | 1 |
| 8 | 1 | 2 |
| 9 | 1 | 3 |
| 10 | 0.5 | 1 |
| 11 | 0 | 2 |
| 12 | 1 | 1 |
| 13 | 0 | 3 |
| 14 | 1 | 2 |
| 15 | 0 | 1 |
| 16 | 0 | 1 |
| 17 | 0.5 | 3 |
| 18 | 0 | 3 |
| 13 | 0.5 | 3 |
Here's my sql query I'm using to concatenate data:
SELECT class AS lesson,
GROUP_CONCAT( bills ORDER BY bills ) AS bills
FROM tb_presence
GROUP BY class;
Here's my result below:
| class | bills |
|-------|------------------|
| 1 | 1,0.5,0.5,1,0,0 |
| 2 | 0.5,0,1,0,1 |
| 3 | 1,1,0,0.5,0,0.5 |
Now I would like to count the data that are equal, but continue with the same concatenation.
I want to "count" the data with the same values and display concatenated (column observation and only to help understanding)
| class | bills | observation |
|-------|-------|-----------------------------|
| 1 | 2,2,2 | (2=0+0) (2=0.5+0.5) (2=1+1) |
| 2 | 2,1,2 | (2=0+0) (1=0.5) (2=1+1) |
| 3 | 2,2,2 | (2=0+0) (2=0.5+0.5) (2=1+1) |
Is this really possible?
Here is a solution (thanks to #wchiquito for the sqlfiddle) See http://sqlfiddle.com/#!2/2d2c8/1
As you can see it cannot dynamically determine the bills' values and count them. But there is a count per bill value that you want.
SELECT class AS lesson,
GROUP_CONCAT( bills ORDER BY bills ) AS bills
,SUM(IF(bills=0,1,0)) AS Count0
,SUM(IF(bills=0.5,1,0)) AS Count05
,SUM(IF(bills=1,1,0)) AS Count1
,COUNT(*) AS totalRecords
,COUNT(*)
- SUM(IF(bills=0,1,0))
- SUM(IF(bills=0.5,1,0))
- SUM(IF(bills=1,1,0))
AS Missing
FROM tb_presence GROUP BY class;
I added an extra record to show how the 'missing' column could show if you were not taking all values into consideration.
Results
| LESSON | BILLS | COUNT0 | COUNT05 | COUNT1 | TOTALRECORDS | MISSING |
|--------|-----------------------------------------|--------|---------|--------|--------------|---------|
| 1 | 0.00,0.00,0.50,0.50,1.00,1.00,1.00,4.00 | 2 | 2 | 3 | 8 | 1 |
| 2 | 0.00,0.00,0.50,0.50,1.00,1.00 | 2 | 2 | 2 | 6 | 0 |
| 3 | 0.00,0.00,0.50,0.50,1.00,1.00 | 2 | 2 | 2 | 6 | 0 |