mysql query the latest date - php

I am running this query
SELECT sh.*,
u.initials AS initals
FROM database1.table1 AS sh
JOIN database2.user AS u ON u.userID = sh.userid
WHERE id = 123456
AND dts = ( SELECT MAX(dts) from database1.table1 )
ORDER BY sort_by, category
In the table1 I have records like this
dts status category sort_by
2010-04-29 12:20:27 Civil Engineers Occupation 1
2010-04-28 12:20:27 Civil Engineers Occupation 1
2010-04-28 12:20:54 Married Marital Status 2 2010-04-28 12:21:15 Smoker Tobbaco 3
2010-04-27 12:20:27 Civil Engineers Occupation 1
2010-04-27 12:20:54 Married Marital Status 2 2010-04-27 12:21:15 Smoker Tobbaco 3
2010-04-26 12:20:27 Civil Engineers Occupation 1
2010-04-26 12:20:54 Married Marital Status 2 2010-04-26 12:21:15 Smoker Tobbaco 3
If you look at my data, I am choosing the latest entry by category and sort_id. however in some case such as on 29th (2010-04-29 12:20:27) I have only one record. So in this case I want to show occupation for latest and then the rest of them (latest). But currently it displays only one row.

trying as best to guess at what you have, your query would have to be adjusted anyhow, something like
SELECT
sh.dts,
cast( if( preAgg1.totalPerCatSort = 1, sh.status, ' ' ) as char(20))
as SingleStatus,
sh.category,
sh.sort_by,
u.initials AS initals
FROM
database1.table1 AS sh,
database2.user AS u,
( select
t1.category,
t1.sort_by,
max(dts) maxdts,
count(*) totalPerCatSort
from
database1 t1
group by
t1.category,
t1.sort_by ) preAgg1
WHERE
sh.userid = u.userID
and sh.sort_by = preAgg1.sort_by
and sh.category = preAgg1.category
and sh.dts = preAgg1.maxdts
and id = 123456 ?? Should this actually be the UserID column ??
ORDER BY
sort_by,
category
you may have to apply the "ID = 123456" into the "preAgg1" sub-select, but again, not sure which ID that column / table was applicable for, otherwise, you could have other date entries by other "users" and not the same for the one candidate person you are looking for... Your call.
Per your concern of getting ALL records, I would just remove your "and ID = 123456" qualifier and all should be good

Related

mysql join 3 tables related in pairs

► Context : I work in a museum (for real), people come everyday, they buy tickets for themselves (humans) and sometimes they also buy tickets for drinks and foods (objects). There are events, tickets have the same names per event but the prices are different.
► The problem : I have to create a report with 2 results : total sales (visitors + food + drinks) and how many people came (visitors only) for a specific event. Next is an image of the 3 tables in the database, how they relate and some sample data :
Table TICKETS relates to SALES_MAIN through EVENT_ID column.
Table SALES_MAIN relates to SALES_DETAIL through ID→MAIN_ID columns.
Table SALES_DETAIL have a column TICKET_NAME but it's not unique in table TICKETS.
► The question : How to get both results, total sales and human count, for event 555 in one "select" ? I tried next 2 "select" but when I combine them with another INNER JOIN I get cartesian results :
Get detail sales for event 555 :
SELECT sales_detail.* FROM sales_main
INNER JOIN sales_detail ON sales_detail.main_id = sales_main.id
WHERE sales_main.event_id = '555'
Get tickets for event 555 :
SELECT * FROM tickets WHERE tickets.event_id = '555'
Use:
SELECT
SUM(CASE WHEN sd.ticket_name IN ('adult', 'child') THEN sd.quantity
ELSE 0 END) AS total_visitors,
SUM(sd.quantity * t.price) AS total_sales
FROM sales_main sm
JOIN sales_detail sd
ON sd.main_id = sm.id
JOIN ticket t
ON t.event_id = sm.event_id
AND t.ticket_name = sd.ticket_name
WHERE sm.event_id = '555';
Conditional aggregation could also be based on type:
SUM(CASE WHEN t.ticket_type ='human' THEN sd.quantity ELSE 0 END)

SQL selecting from multiple tables and ordering by certain conditions

I have 2 tables, customer and tickets
I want to be able to select from the tickets table and order by:
tickets.priority then customer.category_priority then tickets.queue_time
I have this query:
SELECT t.*
from tickets t
JOIN customer c ON t.company = c.sequence
WHERE t.status <> 'Completed' AND t.queue = 'Y'
ORDER BY field(t.priority, 'Critical', 'High', 'Medium', 'Low'), t.queue_time ASC
which works great for the tickets.priority and tickets.queue_time
but im not sure how to incorporate the customer.category_priority
so in the customer table, i have columns with names like:
priority_computers
priority_telephone
priority_software
all INT fields and have a value of 0, 1 or 2
the row in tickets has a category column which is either Computers, Telephone, or Software and thats what needs to link to the above.
so, if a customer row has priority_computers of 2 and the tickets row is category = 'Computers' that would be at the top of the list because the customer record has the priority of 2 and it would also incorporate the other ORDER BY conditions
Examples:
Customers:
Company A priority_computers = 1
Company B priority_computers = 2
Company C priority_computers = 3
Example One:
Ticket 1 Company A priority = Medium category = Computers
queue_time = 2015-11-20 08:00
Ticket 2 Company B priority = Medium category = Computers
queue_time = 2015-11-20 10:00:00
Ticket 3 Company C priority = Medium category = Computers
queue_time = 2015-11-20 08:30:00
This should output in the following order:
Ticket 3
Ticket 2
Ticket 1
Example 2:
Ticket 1 Company B priority = High category = Computers
queue_time = 2015-11-20 12:00
Ticket 2 Company A priority = Medium category = Computers
queue_time = 2015-11-20 07:00:00
Ticket 3 Company C priority = Medium category = Computers
queue_time = 2015-11-20 07:00:00
This should output in the following order:
Ticket 1
Ticket 3
Ticket 2
If I understand this correctly, then your problem is that you have to match data with column names somehow.
customer.priority_computers for ticket.category = 'Computers'
customer.priority_telephone for ticket.category = 'Telephone'
customer.priority_software for ticket.category = 'Software'
This shows a database design flaw. There should be a customer_priority table instead with each row holding a customer, a category and the associated value. Then you could simply join.
As is, you must check data content and decide for a column to use in your query:
SELECT t.*
from tickets t
JOIN customer c ON t.company = c.sequence
WHERE t.status <> 'Completed' AND t.queue = 'Y'
ORDER BY field(t.priority, 'Critical', 'High', 'Medium', 'Low')
, case t.category
when 'Computers' then c.priority_computers
when 'Telephone' then c.priority_telephone
when 'Software' then c.priority_software
end
, t.queue_time ASC
Update: Here is a query you'd write, if you had a customer_priority table. You see, your query doesn't need to know what categories exist and how to treat them any longer.
SELECT t.*
from tickets t
JOIN customer c ON t.company = c.sequence
JOIN customer_priority cp ON cp.customer_id = c.sequence
AND cp.category = t.category
WHERE t.status <> 'Completed' AND t.queue = 'Y'
ORDER BY field(t.priority, 'Critical', 'High', 'Medium', 'Low')
, cp.priority_value
, t.queue_time ASC
Moreover: As mentioned, it is strange to have a table customer, but in tickets it's not called a customer, but a company, and in the customer table itself it's not called a customer number or ID either, but a sequence. This makes the queries less readable. I suggest, you change the names, if possible, so they are consistent.
Also your query shouldn't have to know what 'Critical' and 'High' means. There should be a table for priorities where each priority has a name and a value, so the query could simply pick the value and work with it without having to know anything else about the priorities.

data from two tables without join

Table "subjects" contains columns:
sub_date, sub_content, student_id
2014-10-03, english, 1
2014-10-09, maths, 2
2014-10-11, biology, 1
and
Table games contains columns:
game_date, game_content, student_id
2014-10-05, Hockey, 1
2014-10-18, Tennis, 1
2014-10-20, Cricket, 2
I want to display all details of student_id 1 order by date (considering both sub_date and game_date
Date, Topic
2014-10-03, english
2014-10-05, Hockey
2014-10-11, biology
2014-10-18, Tennis
Please help
you could try this:
select sub_date,sub_content from subjects where student_id = 1
UNION
select game_date,topic from games where student_id = 1
You can try with this (even though sounds not such as a good idea):
SELECT tmp.sub_date AS Date,tmp.sub_content AS Topic
FROM (
SELECT sub_date,sub_content,student_id FROM subjects
UNION SELECT game_date,game_content,student_id FROM games
) tmp
WHERE tmp.student_id = 1 ORDER BY tmp.sub_date;

Getting a daily summary of figures from shop database

I have the following tables, in a standard shop:
(id is always primary key, auto-increment, ts is always type TIMESTAMP, updated ON_UPDATE CURRENT_TIMESTAMP)
table sales:
id | total | tendered | flag | userID | ts
1 0.6 0.6 0 4 2013-11-21 08:12:23
Sales is the parent table, userID is related to the user that made the sale. total and tendered are both of type FLOAT. flag is of type VARCHAR and could be Free Order.
table receipts:
id | oID | pID | quantity | ts
1 1 26 1 2013-11-21 08:11:25
Receipts holds a line for each unique type of product sold. oID is type INT and relates to the id of table sales. pID is of type INT and relates to the id of table products.
table products:
id | name | price | cID | display | ts
1 Mars 0.6 3 1 2014-01-17 07:55:25
Products is the central data for each product in the database. Here is a line for mars bars. cID relates to the id in table categories.
table categories
id | name | display | ts
3 Snacks 1 2013-11-14 12:06:44
Categories is the table holding all the data about each category, and can have multiple products relating to a single row. display is of type INT and dictates when the category is enabled or disabled (1 = 'true')
My question is, I want to output information like this:
**Snacks**
(name) (quantity) (price) (total)
Fruit 3 50p £1.50
Twix 1 60p 60p
Boost 1 60 60p
**Hot Drinks**
(name) (quantity) (price) (total)
English Tea 15 60p £9.00
Speciality Teas 2 60p £1.20
Which I have the following SQL for:
SELECT categories.name AS category, products.name, pID,
(SELECT SUM(quantity) FROM receipts WHERE pID=r.pID AND DATE(ts) = CURDATE()) AS quantity,
products.price,r.ts
FROM receipts r
LEFT JOIN products ON r.pID = products.id
LEFT JOIN categories ON products.cID = categories.id
WHERE DATE(r.ts) = CURDATE()
GROUP BY r.pID
ORDER BY categories.name;
Which seems to give me the correct information, but I am not 100% certain. If anyone could verify that this works, I would be most grateful. But when I want to see a particular day, I get unusual figures with the following SQL:
$postfrom = $_POST['from_mm']."/".$_POST['from_dd']."/20".$_POST['from_yy'];
$postto = $_POST['to_mm']."/".$_POST['to_dd']."/20".$_POST['to_yy'];
$from = strtotime($postfrom . " 6:00");
$to = strtotime($postto . " 23:59");
$itemised = select("SELECT categories.name AS category, products.name, pID,
(SELECT SUM(quantity) FROM receipts WHERE pID = r.pID AND UNIX_TIMESTAMP(r.ts) > '{$from}' AND UNIX_TIMESTAMP(r.ts) < '{$to}')
AS quantity, products.price
FROM receipts r
LEFT JOIN products ON r.pID = products.id
LEFT JOIN categories ON products.cID = categories.id
WHERE UNIX_TIMESTAMP(r.ts) > '{$from}'
AND UNIX_TIMESTAMP(r.ts) < '{$to}'
GROUP BY r.pID
ORDER BY categories.name;");
(function 'select' simply returns an array of the SQL table). The thing is, I could find the results easily by looping through in PHP and adding it up that way. But I know this is possible with SQL, I just don't know why It isnt working. Can somebody please help?
Edit SQL sample fiddle is here: http://sqlfiddle.com/#!2/23af4 although I couldn't do more than half a day of data due to 8000 character restrictions.
Try this:
SELECT categories.name AS category, products.name AS name,
receipts.quantity AS quantity, products.price AS price,
(receipts.quantity * products.price) AS total
FROM categories
JOIN products
ON categories.id = products.cID
JOIN receipts
ON receipts.pID = products.ID
WHERE DATE(receipts.ts) = CURDATE()
ORDER BY categories.name
SQLFiddle demo
With regard to the date restriction, you could use BETWEEN ... AND ... to specify the date and time. Using an absolute date and time moment or relative to the current day and time, for example WHERE DATE(receipts.ts) BETWEEN concat(curdate() -5,' 6:00:00 AM') AND curdate() -4

PHP MySQL Query

Currently I have 3 MySQL tables, one filed with the users information, one with their course history and the last one filled with their reward history.
I am attempting to create a "rewards" program if you will, using these two databases and a PHP script. As far as the reward requirements, I have 2 arrays setup for the two types of rewards:
//Pen Reward with course A & B required
$pen=array("a","b")
//Cup Reward with course B & C required
$cup=array("b","c")
I can't figure out how to first query for all user IDs, then go through their history. If they match the requirements set above, then to update the reward table to 1 (to show that they received the award)
UsersDB
userid name
----------------
1 bill
2 john
3 steve
HistoryDB
userid courseid
------------------
1 a
1 b
2 b
3 a
3 c
RewardHistoryDB
userid pen cup
---------------------
1 0 0
2 0 0
3 0 0
Ideally it after the PHP script runs, it would update the RewardHistoryDB to reflect that user 1 received a pen, and user 3 received a cup.(the DB would look like this:)
RewardHistoryDB (after)
userid pen cup
---------------------
1 1 0
2 0 0
3 0 1
Here is the PHP code I am using right now (not complete):
$userid=array();
$i=0;
//Find All users
$result = mysqli_query($con,"SELECT userid FROM usersdb")
while ($row = mysqli_fetch_array($result)){
$universityid[$i]=$row['universityid'];
$i++;
}
//Find History
$courseid=array();
foreach ($userid as $userid1){
$result = mysqli_query($con,"SELECT courseid FROM historydb WHERE userid='".$userid1."'");
while ($row = mysqli_fetch_array($result)){
$courseid[]=$row;
}
}
//Update Reward DB
//Don't even know where to start...
Any help would be greatly appreciated.
If you have any questions, please let me know.
Thank you in advanced!
http://sqlfiddle.com/#!2/1a96b/1/0
You can do this just as queries and without doing any logic in PHP
update RewardHistoryDB
set Pen = 1
where UserID in (
select UserID
from HistoryDB
where CourseID in ('A','B')
group by UserID
having count(UserID)=2);
update RewardHistoryDB
set Cup = 1
where UserID in (
select UserID
from HistoryDB
where CourseID in ('B','C')
group by UserID
having count(UserID)=2);
Or you can even do it in one, large statement...
update RewardHistoryDB
left outer join (
select UserID as Pens_UserID
from HistoryDB
where CourseID in ('A','B')
group by UserID
having count(UserID)=2 ) as Pens
on RewardHistoryDB.UserID = Pens.Pens_UserID
left outer join (
select UserID as Cups_UserID
from HistoryDB
where CourseID in ('B','C')
group by UserID
having count(UserID)=2 ) as Cups
on RewardHistoryDB.UserID = Cups.Cups_UserID
set Pen = case when Pens.Pens_UserID is not null then 1 else 0 end,
Cup = case when Cups.Cups_UserID is not null then 1 else 0 end

Categories