would it possible to do this in one mysql query only - mysql

Could this be done with one query?
table day:
dID
enable
holiday
fewMore
table segment:
d_ID //foregn key to day->dID
startTime
endTime
fewMore
query:
SELECT dID, enabled,holiday,
TIME_TO_SEC(dHaurs) as wsTimeHHmm,
DATE_FORMAT(dDate, '%d') as dateForComparing,
DATE_FORMAT(start, '%H:%i') as startTime,
DATE_FORMAT(end, '%H:%i') as endTime
FROM day d
LEFT JOIN segment ws
ON ws.d_ID = d.dID
WHERE dDate BETWEEN '" . $startDate . "' AND '" . $endDate . "'
ORDER by dateForComparing
result I am getting:
dID:10, start time:08:00, end time:09:00, holiday:0, enabled:1
dID:10, start time:09:00, end time:10:00, holiday:0, enabled:1
dID:11, start time:08:00, end time:10:00, holiday:1, enabled:1
but I would like to group all segments with same d_ID.
dID:10, array((start time:08:00, end time:09:00),(start time:09:00, end time:10:00)), holiday:0, enabled:1
I tried with GROUP_CONCAT(wsID,start, end) ... GROUP BY dID but I am not sure is that right way and also I am not able to use function DATE_FORMAT(start, '%H:%i') as startTime
could this be done with mysql only?
UPDATE:
right now, I am creating array from result:
$returnData [] =array(array(dID =>"dID",
endTime => $end_time,
startTime=> $start_time,...
),
array( enabled=> $enabled,
holiday =>$holiday
)
);
echo json_encode($returnData);

You can't return arrays in MySQL, but you could manipulate the output like this:
dID:10, start time:08:00, end time:10:00, holiday:0, enabled:1

Related

How can I update an interval of dates in the database (Hibernate HQL)

Consider, for some specific database entry of id id, an interval of dates in the database, from BEGIN_DATE to END_DATE, denoted by (BEGIN_DATE,END_DATE).
Given two new dates, that form the interval (newBeginDate, newEndDate), I must update (BEGIN_DATE,END_DATE) so that the resulting interval contains all 4 dates. In other words, I want to add the two intervals (And since I am adding them, the resulting interval may remain the same or grow, but never shrink).
A few examples:
If (BEGIN_DATE,END_DATE) = (January 10,January 20), then:
(BEGIN_DATE,END_DATE) + (Jan 15,Jan 25) = (Jan 10,Jan 25)
(BEGIN_DATE,END_DATE) + (Jan 05,Jan 15) = (Jan 05,Jan 20)
(BEGIN_DATE,END_DATE) + (Jan 05,Jan 25) = (Jan 05,Jan 25)
(BEGIN_DATE,END_DATE) + (Jan 15,Jan 15) = (Jan 10,Jan 20)
(BEGIN_DATE,END_DATE) + (Jan 10,Jan 13) = (Jan 10,Jan 20)
The two following queries together achieve this goal. The first one updates BEGIN_DATE, and the second updates END_DATE:
session.createQuery(
"update APPOINTMENTS " +
"set BEGIN_DATE = :newBeginDate " +
"where " +
"(BEGIN_DATE is null or BEGIN_DATE > :newBeginDate) " +
"and ID = :id ")
.setParameter("newBeginDate", newBeginDate)
.setParameter("id", id)
.executeUpdate();
session.createQuery(
"update APPOINTMENTS " +
"set END_DATE = :newEndDate " +
"where " +
"(END_DATE is null or END_DATE < :newEndDate) " +
"and ID = :id ")
.setParameter("newEndDate", newEndDate)
.setParameter("id", id)
.executeUpdate();
My question is:
How can I do it in a single query?
SQL is limited when it comes to more complex programming constructs, so since you use Hibernate I would just read the appointment entity instance and update its fields. That would require two queries, one to read and one to update, but still it would be only one update statement and is the most readable solution.
If you still want only one update statement and nothing else, your two statements could be merged into one by using case:
update APPOINTMENTS
set BEGIN_DATE = case when (BEGIN_DATE is null or BEGIN_DATE > :newBeginDate) then :newBeginDate else BEGIN_DATE end,
END_DATE = case when (END_DATE is null or END_DATE < :newEndDate) then :newEndDate else END_DATE end
where (BEGIN_DATE is null or BEGIN_DATE > :newBeginDate or END_DATE is null or END_DATE < :newEndDate)
and ID = :id
Use LEAST() and GREATEST() functions. For NULLs use COALESCE().
update APPOINTMENTS
set BEGIN_DATE = coalesce(least(BEGIN_DATE, :newBeginDate), :newBeginDate),
END_DATE = coalesce(greatest(END_DATE, :newEndDate), :newEndDate)
where ID = :id
I think LEAST and GREATEST don't need an explanation. COALESCE will pick the new date, if the old one is NULL. So no condition except of ID = :id is needed in the WHERE clause.

Multiple MYSQL Queries against one PHP variable

I've broken down individual SQL queries for the information I want from my SQL table but I'm confused on how I can combine all statements agianst one variable. This variable is being used in PHP to display my data.
Here is the SQL queries I'm wanting to run.
SELECT * FROM weather ORDER BY stamp DESC LIMIT 1
SELECT SUM(rainfall) FROM weather WHERE stamp >= CURDATE()) AS total_rainfall
SELECT MAX(maxwind) FROM weather WHERE stamp >= CURDATE()) AS max_windspeed
SELECT MAX(temperature) FROM weather WHERE stamp >= CURDATE()) AS max_temperature
SELECT MIN(temperature) FROM weather WHERE stamp >= CURDATE()) AS min_temperature
Here is my current query which gives me everything I want except the max windspeed, max temperature, and minimum temperature for the last 24 hours.
SELECT *, (SELECT SUM(rainfall) FROM weather WHERE stamp >= CURDATE()) AS total_rainfall FROM weather ORDER BY stamp DESC LIMIT 1
Basically, I'm just wanting to add the maximum temperature, minimum temperature and maximum windspeed that occured within the current date.
MySQL data table example
Here is the way I'm trying to display the data using PHP.
<?php
$url1=$_SERVER['REQUEST_URI'];
header("Refresh: 60; URL=$url1");
$connectinfo = mysql_connect("***", "***", "***")
or die(mysql_error());
mysql_select_db("raspberrydb001", $connectinfo);
$sql = "SELECT *, (SELECT SUM(rainfall) FROM weatherdata WHERE stamp >= CURDATE()) AS total_rainfall FROM weatherdata ORDER BY stamp DESC LIMIT 1; ";
$result = mysql_query($sql, $connectinfo);
while($row = mysql_fetch_array($result)) {
$windspeed = $row['windspeed'];
$maxwind = $row['maxwind'];
$temperature = $row['temperature'];
$humidity = $row['humidity'];
$rainfall = $row['rainfall'];
$stamp = $row['stamp'];
$d=mktime();
$total_rainfall = $row['total_rainfall'];
echo "<div style='text-align:center'><h5>Temperature: " . $temperature . "(F)" . "<br>" . "Rainfall: " . $total_rainfall . "(in)" . "<br>" . "Wind: " . $windspeed . "(MPH)" . "<br>" . "Humidity: " . $humidity . "(%)" . "<br>" . "</h5></div>";
echo "<div style='text-align:right'><h6>Updated at: " . $stamp . "</h6></div>";
echo "<br>";
}
?>
Thanks
I would propose to split it up into two queries.
First, to collect all your data:
SELECT * FROM weather ORDER BY stamp DESC LIMIT 1
Second, to collect the min/max data:
SELECT
SUM(rainfall) AS total_rainfall,
MAX(maxwind) AS max_windspeed,
MAX(temperature) AS max_temperature,
MIN(temperature) AS min_temperature
FROM
weather
WHERE stamp >= CURDATE())
LIMIT 1

Select date range without year

I am looking around for a solution but have not succeeded so far.
My MySQL table ($people_table) holds birthdays in a column "birthdatetr" of type "date", and the data is stored in the format "YYYY-MM-DD" (example: 1789-04-02)
Depending on the current date, I specify a range of interest.
I am calculating the current week with:
$lastmonday = date('m-d', strtotime('last monday'));
$nextsunday = date('m-d', strtotime('next sunday'));
I would like to Select all rows, where the birthday is within this range. (The application is website with genealogical data, which displays all birthdays that happened in the same week so and so many years ago)
I managed to get it somehow done by calculating the day of the year:
$lastmonday_doy = date('z', strtotime('last monday'));
$nextsunday_doy = date('z', strtotime('next sunday'));
SELECT * FROM $people_table WHERE DAYOFYEAR(birthdatetr) BETWEEN $lastmonday_doy AND $nextsunday_doy;
The idea was to bypass any trouble with the month wrap. But this still does not work when the year wraps. Also, I was concerned whether this is very expensive, because the table may hold >5000 rows in the future.
Finally, the DAYOFYEAR() approach does not take leap years into account.
At the moment, there is another implementation roughly working, but I don't understand it and I cannot change it for that reason. It looks very complex:
$query = "SELECT birthdatetr, YEAR(birthdatetr) AS BirthYear, birthdatetr + INTERVAL YEAR('" . $datetouse . "') - YEAR( birthdatetr ) + ( (birthdatetr + INTERVAL YEAR('" . $datetouse . "') - YEAR( birthdatetr ) YEAR) < '" . $datetouse . "') YEAR as nextbirthday
FROM $people_table
WHERE DATEDIFF( birthdatetr + INTERVAL YEAR('" . $datetouse . "') - YEAR( birthdatetr ) + ( ( birthdatetr + INTERVAL YEAR('" . $datetouse . "') - YEAR(birthdatetr) YEAR) < '" . $datetouse . "') YEAR, '" . $datetouse . "') <= $futuredays ORDER BY nextbirthday, birthdatetr";
Here, the current date is $datetouse, and the $futuredays specifies the length of the range. (in this example, $futureday=7; )
Is there a light-weight way to SELECT desired data?
Thanks!
For the one week requirement could be simpler to replace the
WHERE DAYOFYEAR(birthdatetr) BETWEEN $lastmonday_doy AND $nextsunday_doy
with
WHERE DAYOFYEAR(birthdatetr) in (7 day numbers for the 7 weekdays)
and pass 7 parameters to the query (monday, tuesday... sunday)
Ok, here is the final SQL statement. Thanks to StanislavL:
SELECT birthdatetr as datedisplay FROM tng_people
WHERE DATE_FORMAT(birthdatetr, '%m-%d') IN ('05-12', '05-13', '05-14', '05-15', '05-16', '05-17', '05-18')
UNION ALL
SELECT deathdatetr as datedisplay FROM tng_people
WHERE DATE_FORMAT(deathdatetr, '%m-%d') IN ('05-12', '05-13', '05-14', '05-15', '05-16', '05-17', '05-18')
UNION ALL
SELECT marrdatetr as datedisplay FROM tng_families
WHERE DATE_FORMAT(marrdatetr, '%m-%d') IN ('05-12', '05-13', '05-14', '05-15', '05-16', '05-17', '05-18')
ORDER BY DAYOFWEEK(datedisplay)

Performing column operations in CASE WHEN statment condition in sql query

I'm developing an application using vb.net2008 with database as msaccess. I've designed a table in database having columns IN_TIME and OUT_TIME in format HH:MM:SS . I want a result as TOT_TIME which will display difference between these two columns. I've written a query for this, now i'm facing a problem that i dont want to display result if IN_TIME is less than 8:00:00 AM else display result. I have used CASE WHEN but it didnt worked, help me out.
I've tried this so far
SELECT *
(CASE WHEN LATE_LIMIT > '" + date3 + "'
THEN ROUND(([PM_OUT]-[OVERIME_LIMIT]),2)
ELSE 'N' )AS OverTime
FROM DTR_REC
You are missing a comma and an END case:
SELECT *
,(CASE WHEN LATE_LIMIT > '" + date3 + "'
THEN ROUND(([PM_OUT]-[OVERIME_LIMIT]),2)
ELSE 'N' END)AS OverTime
FROM DTR_REC
But I'm not sure if Access supports CASE statements. If not does this work:
SELECT *
,IIF(LATE_LIMIT > '" + date3 + "', ROUND(([PM_OUT]-[OVERIME_LIMIT]),2),'N') AS OverTime
FROM DTR_REC

Query for choose all orders from all restaurants for the current day

How can I write a mysql query that will choose all the orders of all restaurants for the current day?
Some restaurants may close after 24:00.
So I have three tables:
restaurants with some fields [id, ]
orders with some fields [id, resid, orderdate, ]
hours with some fields [id, resid, day, open, close] the day is a number from 0-6, the open and close are time between 00:00:00 and 23:59:59
Thank you
This is what about i need
SELECT b.*
FROM restaurants a, orders b, hours c
WHERE a.id=b.resid
AND a.id=c.resid
---- here i need the code that will choose the orders for the current working day of the restaurant, but the current working day may include some orders from the previous calendar day if the restaurant close after 24:00
Is this what you want?
select o.*
from orders o
where o.orderdate = curdate();
If not, can you modify your question to better explain what you want?
Because you did not give much information, so I make 2 assumption here
Assumption 1: You run this query at 1AM and want to get all order your 1AM yesterday till now
Assumption 2: No restaurant open 24h day
hours.day = WEEKDAY(SUBDATE(CURDATE(), 1)
If hours.close < hours.open mean restaurant open from YESTERDAY + open_time to TODAY + close_time, otherwise it is open and close on YESTERDAY
STR_TO_DATE(CONCAT(DATE_FORMAT(SUBDATE(CURDATE(), CASE WHEN c.close < c.open THEN 1 ELSE 0 END), '%Y%m%d'), c.close), '%Y%m%d%T')
So your query is something like
SELECT b.*
FROM restaurants a, orders b
WHERE a.id=b.resid
AND a.id in (
select c.resid
from hours c
where c.day = WEEKDAY(SUBDATE(CURDATE(), 1)
and STR_TO_DATE(CONCAT(DATE_FORMAT(SUBDATE(CURDATE(), 1), '%Y%m%d'), c.open), '%Y%m%d%T') > SUBDATE(CURDATE(), 1)
and STR_TO_DATE(CONCAT(DATE_FORMAT(SUBDATE(CURDATE(), CASE WHEN c.close < c.open THEN 1 ELSE 0 END), '%Y%m%d'), c.close), '%Y%m%d%T') <= CURDATE()
)
I'm not sure about orders.orderdate, so you should update your filter on orders table to get correct data you want.
Hope this help
The solution is
" SELECT b.*".
" FROM orders b, rests a, times c ".
" WHERE a.id=b.resid ".
" AND a.id=c.resid ".
" AND (".
"( c.day=dayofweek(subdate(current_date, 1))-1 " .
" AND c.close < c.open " .
" AND c.close> TIME(NOW())" .
" AND b.orderdate>= CONCAT(subdate(current_date, 1),' ',c.open) )" .
" OR " .
"( c.day=dayofweek(current_date)-1 " .
" AND c.close >= c.open " .
" AND c.close> TIME(NOW())" .
" AND b.orderdate>= CONCAT(current_date,' ',c.open) )" .
" OR " .
"( c.day=dayofweek(current_date)-1 " .
" AND c.close < c.open " .
" AND CONCAT(ADDDATE(CURRENT_DATE, 1),' ',c.close)> TIME(NOW())" .
" AND b.orderdate>= CONCAT(current_date,' ',c.open) )" .
")";