MySQL - SELECT WHERE condition based on value of another SELECT - php

Hello I have two MySQL Querys where I am trying to use count and results from first select in condition for the second select.
Here is my code:
$sql = "SELECT m.name, m.id
FROM members m
WHERE m.online_status = 1 {$dep} ORDER BY m.name ASC";
$sql_second = "SELECT time_management.clientid, clients.client,
SUM( CASE WHEN MONTH(`date`) = 1 AND taskid <> 1 AND YEAR(date)='$year' THEN TIME_TO_SEC( `time` ) AND user = (result from previouse slect) ELSE 0 END) AS (user_1)
FROM time_management
LEFT JOIN clients ON time_management.clientid = clients.id
WHERE {$dep_where} = {$department_var}
GROUP BY clientid";
So first select is selecting all users which are unknown value. Name and ID
In the second query what I need is to Select for example:
let's say the first query returns
id:1 name: Jon
id:2 name: Mike
id:3 name: Dave
Total results: 3
so in this case in the second query the following line have to be repeaded 3 times for each user:
SUM( CASE WHEN MONTH(`date`) = 1 AND taskid <> 1 AND YEAR(date)='$year' THEN TIME_TO_SEC( `time` ) AND user = (result from previouse slect) ELSE 0 END) AS (user_1)
where user will be = to 1,2,3 for each line and (user_1) willbe (user_2), (user_3)
Is there a way this operation to be realized directly inside MySQL ? if now how it should be solved ?

Related

PHP and MySQL query output different

I have the following query. When I run the query straight in MySQL I get all the information but when I run the same query in my PHP script it's missing some information. I ran the query in MySQL first to make sure that I I get everything I need and then copied the query into my php script. Can anyone please help:
$get_attendance_profile_stmt = $conn->prepare('SELECT
p_info.fname AS \'First name\',
p_info.lname AS \'Lastname\',
stud_info.t_belt_id,
t_b.short_descr,
t_b.long_descr,
stud_info.h_belt_id,
h_b.short_descr,
h_b.long_descr,
AB.*,
ROUND(
(
AB.Considered_Attended / AB.Classes_Tought * 100
),
0
) AS \'Attendance %\'
FROM
(
SELECT
student_id,
SUM(
CASE WHEN attendance_reason = 1 THEN 1 ELSE 0
END
) AS \'Sick\',
SUM(
CASE WHEN attendance_reason = 2 THEN 1 ELSE 0
END
) AS \'Injured\',
SUM(
CASE WHEN attendance_reason = 3 THEN 1 ELSE 0
END
) AS \'Work\',
SUM(
CASE WHEN attendance_reason = 4 THEN 1 ELSE 0
END
) AS \'School\',
SUM(
CASE WHEN attendance_reason = 5 THEN 1 ELSE 0
END
) AS \'Did not attend\',
SUM(
CASE WHEN attendance_reason = 6 THEN 1 ELSE 0
END
) AS \'Present\',
SUM(
CASE WHEN attendance_reason != 5 THEN 1 ELSE 0
END
) AS \'Considered_Attended\',
MAX(DateCounter) AS \'Classes_Tought\'
FROM
attendance a
JOIN(
SELECT COUNT(
DISTINCT CONVERT(creation_date, DATE)
) AS DateCounter
FROM
attendance
WHERE
creation_date <= (SELECT DATE_SUB(NOW(), INTERVAL -6 MONTH))
) DT
WHERE
creation_date <= (SELECT DATE_SUB(NOW(), INTERVAL -1 MONTH))
GROUP BY
student_id
) AB
JOIN student_info stud_info ON
stud_info.student_id = AB.student_id
JOIN users u ON
stud_info.uid = u.uid
JOIN personal_info p_info ON
u.uid = p_info.uid
LEFT JOIN t_belts t_b ON
stud_info.t_belt_id = t_b.t_belt_id
LEFT JOIN h_belts h_b ON
stud_info.h_belt_id = h_b.h_belt_id
WHERE
u.account_status = \'Active\'');
My output running the query inside MySQL is like this:
The output of the query in php looks like this:
Any help will be greatly appreciated.
PHP array's need to have unique indices. Your query returns 2 columns with the same name so the second values are what you get (they overwrite the first during assignment, simple example https://3v4l.org/sbs41 )). As can be seen in the screenshot your second columns are empty. Use an alias on the first columns (or the second) so your indices in PHP are unique. e.g.
SELECT
p_info.fname AS \'First name\',
p_info.lname AS \'Lastname\',
stud_info.t_belt_id,
t_b.short_descr,
t_b.long_descr,
stud_info.h_belt_id,
h_b.short_descr as short_descr_dontcare,
h_b.long_descr as long_descr_dontcare
or
SELECT
p_info.fname AS \'First name\',
p_info.lname AS \'Lastname\',
stud_info.t_belt_id,
t_b.short_descr as short_descr_real,
t_b.long_descr as long_descr_real,
stud_info.h_belt_id,
h_b.short_descr,
h_b.long_descr
with the latter approach you'll need to modify the indices in your PHP array with _real.

Select Nth record from MySQL query from Millions of rows

I have a MySQL query as below; I would like to select the top record for each range of 600 records in a table with 1.8M records. So far I have to loop 3,000 times to accomplish this which is not an efficient solution.
Database Schema;
Table: bet_perm_13predict
id bet_id perm_id avg_odd avg_odd2 avg_odd3
1 23 1 43.29 28.82 28.82
2 23 2 42.86 28.59 28.59
3 23 3 43.13 28.73 28.73
Table: bet_permute_13games
perm_id perm_code
1 0000000000000
2 0000000000001
3 0000000000002
4 0000000000010
Sample MySQL Query in PHP
$totRange = 0; //Used as starting point in rang
$range = 600; //Used as range
$stop = 0;//Used as endPoint of range
while($totRange < 1800000){
$stop = $totRange+$range;
$sql = "SELECT (tb1.avg_odd2 + tb1.avg_odd3) AS totAvg_odd ,
tb1.perm_id , tb1.avg_odd, tb1.avg_odd2, tb1.avg_odd3, tb2.perm_code
FROM bet_perm_13predict tb1
INNER JOIN bet_permute_13games tb2 ON tb2.perm_id = tb1.perm_id
WHERE tb1.bet_id = '$bet_id' && tb1.perm_id
BETWEEN $startRange AND $stop ORDER BY totAvg_odd ASC LIMIT 1"
$q1 = $this->db->query($sql);
$totRange = $stop;
}
In other words I want to select a sample of the data that will represent the entire table with the sample not being random but predefined using the top record in range of 600. So far I have no idea how to proceed. There is no clear online material on this subject.
You can use integer division to create groups.
DEMO
SELECT ID, ID DIV 600 as grp
FROM Table1
Then find the max value on each group. Some options here
Get records with max value for each group of grouped SQL results
For those who might encounter the same issue, this is how I solved it. I used #Juan Carlos suggestion and added a way to pick top record of group using Subquery.
SELECT * FROM
(SELECT * , perm_id DIV $limit as grp , (avg_odd2 + avg_odd3) AS totAvg_odd
FROM bet_perm_13predict WHERE bet_id = '$bet_id' ORDER BY grp ASC ) tb1
INNER JOIN bet_permute_13games tb2 ON tb2.perm_id = tb1.perm_id
INNER JOIN bet_entry tb3 ON tb3.bet_id = tb1.bet_id
WHERE tb1.avg_odd2 < (SELECT AVG(avg_odd2) FROM bet_perm_13predict WHERE bet_id = '$bet_id' )
&& tb1.avg_odd3 < (SELECT AVG(avg_odd3) FROM bet_perm_13predict WHERE bet_id = '$bet_id' )
GROUP BY grp ORDER BY totAvg_odd ASC
LIMIT 100

How get value matching multiple column value of MySQL database

I need to match the multiple same column value of MySQL table using PHP and MySQL. I am explaining my table below.
db_user:
id status book_id
1 0 22
2 0 22
3 1 22
4 0 23
Here I need the select query and condition is if status=0 for same book_id means if table has lets say book_id=22 and all status=0 then only it will return value true otherwise false. I am writing one example below.
$sql=mysqli_query($connect,"select * from db_user where status=0 and....");
if(mysqli_num_rows($sql) > 0){
$row=mysqli_fetch_array($sql);
$data=$row['book_id'];
}else{
return 0;
}
Here as per the example table only last row will fetch because for book_id=22 there is status=1 present. The data will only fetch when for one book_id all status=0.
One option uses aggregation to check the status values:
SELECT book_id
FROM db_user
GROUP BY book_id
HAVING SUM(CASE WHEN status <> 0 THEN 1 ELSE 0 END) = 0;
We can also use EXISTS:
SELECT DISTINCT t1.book_id
FROM db_user t1
WHERE NOT EXISTS (SELECT 1 FROM db_user t2
WHERE t1.book_id = t2.book_id AND t2.status <> 0);
Back in the day, we would have solved it this way. I say, if it ain't broke, don't fix it...
SELECT DISTINCT x.*
FROM my_table x
LEFT
JOIN my_table y
ON y.book_id = x.book_id
AND y.status = 1
WHERE y.id IS NULL;
You could use a not in for the id with status 1
select *
from my_table
where book_id not in (
select book_id
from my_table
where status = 1 )
You can use below query.
select * from db_user where status=0 and book_id not in (select book_id from db_user where status = 1 );
I have tested it and it works.
its very simple:
SELECT book_id,MAX(status) max_status FROM db_user GROUP BY book_id
is max_status is 0 then all is 0 no larger than that.

How to count records in MySQL and merge results in PHP

I have a table which stores clients like this:
id name
-- ----
1 John
2 Jane
...
I also have another table which stores links created by clients:
id client_id link created
-- --------- ---- -----------
1 1 ... 2015-02-01
2 1 ... 2015-02-26
3 1 ... 2015-03-01
4 2 ... 2015-03-01
5 2 ... 2015-03-02
6 2 ... 2015-03-02
I need to find how many links a client has created today, this month and during all the time. I also need their name in the result, so I'll be able to craete a HTML table to display the statistics. I thought I can code as less as possible like this:
$today = $this->db->query("SELECT COUNT(*) as today, c.id as client_id, c.name FROM `links` l JOIN `clients` c ON l.client_id = c.id WHERE DATE(l.created) = CURDATE() GROUP BY c.id");
$this_month = $this->db->query("SELECT COUNT(*) as this_month, c.id as client_id, c.name FROM `links` l JOIN `clients` c ON l.client_id = c.id WHERE YEAR(l.created) = YEAR(NOW()) AND MONTH(l.created) = MONTH(NOW()) GROUP BY c.id");
$yet = $this->db->query("SELECT COUNT(*) as yet, c.id as client_id, c.name FROM `links` l JOIN `clients` c ON l.client_id = c.id WHERE GROUP BY c.id");
And then merge them in PHP as I asked HERE before, like this:
$result = array_replace_recursive($today, $this_month, $yet);
So I'll be able to loop into the result and print my HTML table.
But there are logical problems here. Everything works fine, but the result in a month is a wrong number, forexample the whole created links of one person is 1 but it shows 4 in the monthly counter! I also tried to use RIGHT JOIN in SQL query to get all clients, so array_replace_recursive in PHP could work fine as I think it doesn't work properly at the moment, but no success and got wrong results again.
Can anyone show me a way to make the job done?
This query should do it for today
$query_today="
SELECT name, id AS user_id, (
SELECT COUNT( * )
FROM links
WHERE client_id = user_id AND created = '2015-03-02'
) AS alllinks
FROM clients"
adjust the WHERE clause in the subquery for months and all
$query_month="
SELECT name, id AS user_id, (
SELECT COUNT( * )
FROM links
WHERE client_id = user_id AND created like '2015-03%'
) AS alllinks
FROM clients"
$query_all="
SELECT name, id AS user_id, (
SELECT COUNT( * )
FROM links
WHERE client_id = user_id
) AS alllinks
FROM clients"

Returning Just count of records found in MYSQL query

I have the following MYSQL query which returns the number of photos found for each record where the number of photos is greater than 0.
SELECT advert_id, (SELECT COUNT( * ) FROM advert_images b WHERE b.advert_id = adverts.advert_id) AS num_photos
FROM adverts
WHERE adverts.approve = '1'
HAVING num_photos > 0
The query works fine, but I want to just return a count of the records found. i.e. the number of records which have at least one photo. I've tried to wrap the whole query in a COUNT, but it gives an error. I want to do this in the query, and not a separate count of records found in php.
SELECT COUNT(*) AS TotalRecords
FROM
(
SELECT a.advert_id, COUNT(*) AS num_photos
FROM adverts AS a
JOIN advert_images AS i
ON i.advert_id = a.advert_id
WHERE a.approve = '1'
GROUP BY a.advert_id
HAVING num_photos > 0
) AS mq
SELECT COUNT(*) FROM (SELECT advert_id, (SELECT COUNT( * ) FROM advert_images b WHERE b.advert_id = adverts.advert_id) AS num_photos
FROM adverts
WHERE adverts.approve = '1'
HAVING num_photos > 0) AS c
This should do the trick

Categories