how to display rows with same value in php as a group - php

DATABASE Structure:
ID | USERID | ENTRYDATE | EXITDATE | PRICE | ROOMID
-----------------------------------------------------
1 | 2 | 2012-10-1 | 2012-10-4| 100 | 1
2 | 2 | 2012-10-1 | 2012-10-4| 100 | 2
3 | 2 | 2012-10-1 | 2012-10-4| 100 | 3
4 | 2 | 2012-10-6 | 2012-10-9| 100 | 4
5 | 2 | 2012-10-6 | 2012-10-9| 100 | 55
i need some help please. I want to display a set of records from this database. i want to display all those with same USERID, but group those with the same ENTRYDATE and EXITDATE in the same DIV. example, the result should be like this...
ID | USERID | ENTRYDATE | EXITDATE | PRICE | ROOMID
------------------------------------------------------
1 | 2 | 2012-10-1 | 2012-10-4| 100 | 1
2 | 2 | 2012-10-1 | 2012-10-4| 100 | 2
3 | 2 | 2012-10-1 | 2012-10-4| 100 | 3
ID | USERID | ENTRYDATE | EXITDATE | PRICE | ROOMID
----------------------------------------------------
4 | 2 | 2012-10-6 | 2012-10-9| 100 | 4
5 | 2 | 2012-10-6 | 2012-10-9| 100 | 5

I am not sure I understand your question correctly. I assume you have a string-indexed array and you want to split it basing on ENTRYDATE and EXITDATE values. Maybe something like this:
$currentEntry = $data[0]['ENTRYDATE'];
$currentExit = $data[0]['EXITDATE'];
$splitted = array();
$i = 0;
foreach ($data as $row) {
if ($row['ENTRYDATE'] == $currentEntry && $row['ENTRYDATE'] == $currentExit) {
$splitted[$i] []= $row;
} else {
$currentEntry = $row['ENTRYDATE'];
$currentExit = $row['EXITDATE'];
$i++;
}
}

Related

MySQL - Select next row if previous row field was 1, select first row if next row does not exist?

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);

Laravel extracting elements from collection, and sort it

i have a Collection like that:
+----------+----------+
| user_id | city_id |
+----------+----------+
| 1 | 1 |
| 2 | 1 |
| ... | ... |
| 901 | 2 |
| 902 | 2 |
| ... | ... |
| 1501 | 3 |
| 1502 | 3 |
| ... | ... |
+----------+----------+
in this example i have
900 users for city_id = 1
600 users for city_id = 2
300 users for city_id = 3
what i want to do:
Sort each user in a fair way, so that I end up with a list like this:
+---------+----------+
| user_id | city_id |
+---------+----------+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 901 | 2 |
| 902 | 2 |
| 1501 | 3 |
| 4 | 1 |
| 5 | 1 |
| 6 | 1 |
| 903 | 2 |
| 904 | 2 |
| 1502 | 3 |
+---------+----------+
I divided everything by 300 (for example), so i have by day:
3 users from city 1
then 2 users from city 2
then 1 user from city 3
then 3 users from city 1
then 2 users from city 2
then 1 user from city 3
...
I tried to use the take() function but it doesnt modify the original collection.
And i used the shift() function but it just take one item.
i tried that code:
while($users->isNotEmpty()){
// $user->count() = 1800
for ($i=0; $i<3; $i++){
$final->push($users->where('city_id', 1)->shift());
}
for ($i=0; $i<2; $i++){
$final->push($users->where('city_id', 2)->shift());
}
$final->push($users->where('city_id', 3)->shift());
// $user->count() = 1800; $final->count() = 6
}
it doesn't shift element from $user collection. still have 1800 elements...
Thanks !

Query the database where used for loops

I have a problem calling the database where I used for loops.
database query 1
SELECT id,qtyslot FROM rack WHERE theid = '1'
Eg id = 2
and qtyslot = 12
We create for loops
for ($x = 1; $x <= 12; $x++) {
Here I call the database with the identity of the slot varies
1 or 2,4 (with comma from 2 to 4 slots) and etc.
HOW CAN SELECT
SELECT * FROM books WHERE idrack = '2' AND slot"......." // $x
The database structure as follow.
-----------------------
| id | slot | name |
-----------------------
| 1 | 1 | name |
-----------------------
| 2 | 2,4 | name | --> How to define this with the above loop ($x)
-----------------------
| 3 | 5,6 | name | --> How to define this with the above loop ($x)
-----------------------
| 4 | 7 | name |
-----------------------
And the result like this in table
-----------------------------------------
| loop qtyslot | In slot | remark |
-----------------------------------------
| 1 | name slot 1 | remark |
-----------------------------------------
| 2 | | |
---------------| | |
| 3 | Name slot 2,4 | remark |
---------------| | |
| 4 | | |
-----------------------------------------
| 5 | Name in | |
---------------| slot 5,6 | remark|
| 6 | | |
------------------------------------------
etc up to 12
Can anyone help me.
You can use SUBSTRING_INDEX function in mysql.
Try This :
SELECT * FROM books WHERE idrack = '2' AND $x BETWEEN SUBSTRING_INDEX(slot, ',', 1) and SUBSTRING_INDEX(slot, ',', -1)

How to display dynamic mysql vertical data to horizontal using php

I want to display dynamic mysql vertical data to horizontal in html table using PHP. And my table is like
mysql> select * from role_perm;
-------------------------------------------
| id | userID | roleID | permID | value |
--------------- ---------------------------
| 1 | 2 | 1 | 1 | 1 |
|------------------------------------------
| 2 | 2 | 1 | 2 | 0 |
|------------------------------------------
| 3 | 2 | 1 | 3 | 0 |
|------------------------------------------
| 4 | 2 | 2 | 4 | 0 |
-------------------------------------------
| 5 | 2 | 2 | 1 | 1 |
|------------------------------------------
| 6 | 2 | 2 | 2 | 1 |
|------------------------------------------
| 7 | 2 | 2 | 3 | 0 |
|------------------------------------------
| 8 | 2 | 2 | 4 | 1 |
-------------------------------------------
| 9 | 5 | 1 | 1 | 1 |
|------------------------------------------
| 10 | 5 | 1 | 2 | 0 |
|------------------------------------------
| 11 | 5 | 1 | 3 | 0 |
|------------------------------------------
| 12 | 5 | 1 | 4 | 0 |
-------------------------------------------
and so on...
and i want to display in html table like
----------------------------
| role | permissions |
----------------------------
| 1 | 1 | 2 | 3 | 4 |
----------------------------
| 2 | 1 | 2 | 3 | 4 |
----------------------------
| 3 | 1 | 2 | 3 | 4 |
-----------------------------
| 4 | 1 | 2 | 3 | 4 |
----------------------------
could you pls help me. Thank you in advance.
Try this:
SELECT
roleID AS role,
GROUP_CONCAT(DISTINCT permID ORDER BY permID ASC SEPARATOR '|') AS permissions
FROM role_perm
GROUP BY roleID
ORDER BY roleID
I suppose you could do this with a nifty MySQL query as well (which would supposedly be better for performance), but since I'm not that good at SQL, here's the PHP solution:
$arrRoles = array();
while ($row = mysql_fetch_assoc($result)) {
if (!isset($arrRoles[$row['roleID']])) {
$arrRoles[$row['roleID']] = array();
}
$arrRoles[$row['roleID']][$row['permID']] = $row['value'];
}
var_dump($arrRoles);

SELECT records WHERE rows have difference on a specific column

I have a database table campaign_data. I need to select the customer_id where in the campaign there is difference in tariff. How can i do that with MySQL query. Here is some sample data.
SQL Fiddle Schema
| CAMPAIGN_ID | CUSTOMER_ID | CAMPAIGN_NAME | TARIFF |
---------------------------------------------------------
| 1 | 1 | Richmond | 100 |
| 2 | 1 | Sutton Coldfield | 75 |
| 3 | 1 | Putney | 100 |
| 4 | 1 | Kentish Town | 100 |
| 5 | 1 | Woking | 100 |
| 6 | 2 | Chiswick | 90 |
| 7 | 2 | Ealing | 100 |
| 8 | 2 | Camden | 100 |
| 9 | 3 | Croydon | 75 |
| 10 | 3 | Croydon1 | 100 |
| 11 | 3 | Archway | 100 |
| 12 | 4 | Ealing0 | 100 |
| 13 | 4 | Ealing01 | 100 |
| 14 | 4 | Ealing02 | 100 |
| 15 | 4 | Chingford | 100 |
| 16 | 4 | chingford01 | 100 |
Now as you can see customer id 1 , and 3 has different tariffs. I want to select them and leave the customer id 4 because it has campaigns with same tariffs.
Desired Output
| CUSTOMER_ID |
---------------
| 1 |
| 2 |
| 3 |
For clearification you can see customer 1 has 5 records. If in his 5 records the tariff is same (100) i want to avoid but if the tariff is not some as 4 records have 100 and one has 75, i want to select.
SELECT customer_id, count(DISTINCT tariff) as tariffs
FROM campaign_data
GROUP BY customer_id
HAVING tariffs > 1
you looking for this maybe
SELECT customer_id
FROM campaign_data
GROUP BY customer_id
HAVING count(DISTINCT tariff) > 1
http://sqlfiddle.com/#!2/48b6e/31
select
customer_id,
tariff
from campaign_data
group by customer_id
having sum(tariff)/count(tariff) <> tariff;

Categories