I have a problem where i think exist a couple solutions.
scenario
I have build this intranetpage where internal performance KPI's are visible for the office.
The data is extracted from a MSSQL database and shown on the webpage in combination with PHP, than the data and converted to an array so Google Chart API can create beautiful charts from there.
So far, so good!
Problem
I have a chart where the created tickets from the last 7 days are shown (in reverse order). The number of tickets are created by a MSSQL count, one number for each day (today - 7) in total.
But on some days, no tickets are created like a saterday or sunday. Thats where things go wrong.
Today is Thursday and it shows:
Day Amount
Thursday 25
Friday 10
Monday 30 (etc)
Tuesday 15 (day before)
Wednesday 20 (yesterday)
Thursday 50 (today)
instead of
Saturday 0
Sunday 0
Monday 30
Tuesday 15
Wednesday 20
Thursday 50
The problem is that there are no records (tickets) with a create-date on saturday or sunday, so MSSQL cant count them.
PHP calculates the dates (also today -7) that are shown beneath the axis in my chart, but PHP does include Saterday and Sunday, so the axis titles are not representive for the data that the axis shows.
Possible solution
One solution is that somehow MSSQL shows Saterday and Sunday in the result table. But i dont think this is possible, because the records simply dont exist.
Other solution
Retrieve the datetime used in the MSSQL query and parse them to my intranetpage so the google charts can display those dates instead of the PHP created dates. But than i get a "Convert datetime class to string" error.
Because the datetime in MSSQL is a datetime type and not a varchar type.
After trying a lot of things and searching even more on google and stackoverflow, i can succesfull convert a datetime to varchar. But than the part where i take todays date and go back 7 days, doesnt work anymore.
My PHP (and query) look as follow:
$sql = "
SELECT top 7
CAST(bb_casestartingtime AS DATE) AS DATE, COUNT(*) as TotalRows
FROM
CRM_MSCRM.dbo.FilteredIncident
WHERE
bb_casestartingtime > (CONVERT(date, GETDATE() - 7))
GROUP BY CAST(bb_casestartingtime AS DATE)
Order by date
";
$stmt = sqlsrv_query( $conn, $sql );
if( $stmt === false) {die( print_r( sqlsrv_errors(), true) );}
$x=5;
while( $row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC) )
{ **$dateValue = date("Y-m-d", strtotime(" -$x day"));**
echo "[',".$row[**date**].$row['TotalRows'].",],";
$x--;
}
I broke the two pieces of code in half, but actually they are
The table looks like this (at least, the interesting part):
case id bb_casestartingtime
01 2016-11-10 15:30:45.000
02 2016-11-10 16:22:10.000
03 2016-11-09 15:02:15.000
I count the amount of occurrences by date (bb_casestartingtime) as a total.
So today i have
today 2 records
yesterday 1 record
Acutal Question
can somebody help me to extraced the date-time which is used in the query?
I only use one table called: FilteredIncident
Is there a way to convert the datetime bb_casestartingtime to a varchar (so PHP can extract it) but still count the amount of occurrences per day?
If any information is needed, please ask
Thanks in advance!
(I rewrote my entire question, because i wrote the initial post in a rush)
You could achieve what you're after by creating a date range table and the you can LEFT JOIN to it, so you get 0 for the days with no tickets. You can run this code in isolation to test and it should give you something you can adapt:
-- table for dummy data
CREATE TABLE #FilteredIncident (bb_casestartingtime DATETIME)
-- insert dummy data that has gaps and more than 7 days
INSERT INTO #FilteredIncident
( bb_casestartingtime )
VALUES ( '20161110 12:00'),
( '20161110 11:00'),
( '20161109 10:00'),
( '20161108 13:00'),
( '20161107 09:00'),
( '20161104 07:00'),
( '20161104 05:00'),
( '20161104 16:00'),
( '20161103 18:00'),
( '20161103 19:00')
-- create a date range table for last 7 days
CREATE TABLE #DateRange ( DateVal Date )
-- insert last 7 days
INSERT INTO #DateRange
( DateVal )
VALUES ( GETDATE() )
,( DATEADD(D,-1,GETDATE()))
,( DATEADD(D,-2,GETDATE()))
,( DATEADD(D,-3,GETDATE()))
,( DATEADD(D,-4,GETDATE()))
,( DATEADD(D,-5,GETDATE()))
,( DATEADD(D,-6,GETDATE()))
-- SELECT * FROM #FilteredIncident -- uncomment to see data
-- SELECT * FROM #DateRange -- uncomment to see date range data
SELECT COUNT(fi.bb_casestartingtime) TotalRows, dr.DateVal
FROM #DateRange dr
LEFT JOIN #FilteredIncident fi ON dr.DateVal = cast(fi.bb_casestartingtime AS DATE)
GROUP BY dr.DateVal
ORDER BY dr.DateVal
DROP TABLE #FilteredIncident
DROP TABLE #DateRange
Produces:
TotalRows DateVal
3 2016-11-04
0 2016-11-05
0 2016-11-06
1 2016-11-07
1 2016-11-08
1 2016-11-09
2 2016-11-10
Note:
I'd recommend moving this SQL code in to a stored procedure as opposed to building a string to execute like you are doing.
I solved the problem with a work arround, as i didnt need to see the days where there are 0 tickets, i didnt have to build an temporary table and do a left join.
The solution i came with is to use the datetime fields (bb_casestartingtime) and use those dates. Now the chart axis title matches the chart bar.
solution
Convert the $variable where the datetime field is put to, to a datetime field variable.
$rows[] = "['".$row[1]->format('D j-m')."',".$row[0]."],";
^ ^ ^
The datetime row | The format | The amount of tickets
Related
Hello I am trying to realize a query where from DB with hours and dates I can select sum of all hours for certain department, in certain year.
Table example is the following:
So far the query which I am generating is the following:
SELECT t.clientid, t.date, t.department, t.time,
(SELECT SEC_TO_TIME( SUM( TIME_TO_SEC( `time` ) ) ) FROM time_management WHERE YEAR(t.date)='$year' AND MONTH(t.date)= 12 GROUP BY t.clientid ) as january,
(SELECT SEC_TO_TIME( SUM( TIME_TO_SEC( `time` ) ) ) FROM time_management WHERE YEAR(t.date)='$year' AND MONTH(t.date)= 2 GROUP BY t.clientid ) as february
FROM time_management t GROUP by t.clientid
What I would like this to do is select sum of all hours for the month of January 2016. in the current state I am getting the result of sum of all hours for all clients and I would like to get result for client by client:
Current Result is:
So what I am searching for is how to get the sum of the times result grouped by clientid and get 2 results not only one. The sum for both client id. independently summed for each one of them ?
Any help will be very appreciate. Thank you!
You should be able to do that without the subquery -
SELECT `date`, `department`, SUM(`time`)
FROM `time_management`
WHERE YEAR(`date`)='$year' AND MONTH(`date`)= 12
GROUP BY `client_id`
I recommend you store you time in the database in seconds - the only time it needs to show as hours and minutes is when it's formatted to show on the client's screen. If you do store it as strings, you will have to put all that converting stuff back in.
Looking at it more, I'd also recommend storing your year and month either as separate columns, or as integers based on a pattern: 201612, perhaps, or something like that. That will clean up your where clause as well.
In my SQL database I store date with time stamp for example like this(2015-09-21 18:02:14) I have requirement to get last time(18:02:14) is Day or Night using SQL statement
If you have another idea please share with me. I would like to use it if it fits my requirements.
In my table if have 20 record same date then get only day record how to create query like that
If the day defines from 6am to 6pm, Then
SELECT column
FROM `tablename`
WHERE HOUR( column )
BETWEEN 6
AND 18;
First you should define what is a day and night. Then you can use DATE_FORMAT function to convert datetime field to HH:MI string.
For example you can select records from 18:00 to 8:00 (Night)
select * from t
WHERE DATE_FORMAT(dt, '%H:%i')>='18:00'
or DATE_FORMAT(dt, '%H:%i')<'09:00'
SQLFiddle demo
You should have another table (or other data source) that supplies the sunset and sunrise times, then compare you own datetime, to that source. You can compare either before adding to your table (and make another column named isDay) or when SELECTing from the table.
Note:
Sunset/Sunrise times depend on your geo-location.
There are API's that can provide that info
There are algorithms that can assist in calculating that info
Examples:
http://sunrise-sunset.org/api
http://api.sunrise-sunset.org/json?lat=36.7201600&lng=-4.4203400&date=2015-12-13
I need a sunrise/sunset webservice api
-- from sql server 2008 until now
SELECT
CASE WHEN DATEPART(HOUR, GETDATE()) < 18 THEN 'DAY'
ELSE 'NIGHT'
END
-- from sql server 2012 until now, if you don't like CASE
SELECT IIF(DATEPART(HOUR, GETDATE()) < 18, 'DAY', 'NIGHT')
18 = 6PM
you can replace GETDATE() with your DATETIME column
SELECT
CASE WHEN DATEPART(HOUR, 'yourDateTimeColumn') < 18 THEN 'DAY'
ELSE 'NIGHT'
END AS PeriodOfDay
FROM 'yourTable'
I want to create a query for fetch all the data from database. But condition is get from before current month and data will convert into 3 days slot wise with count.Like if i have 12 month data and in July 1 to 3 date data will insert into 50 rows and from 3 to 6 date data will insert into 5 rows.How i fetch this things.That is the mail problem. I have wondered but nothing found related my problem. Is this possible.
I assume you have a DATE or a DATETIME column, that marks the day of the insert, say the column created_at. Then you could get the desired result.
SELECT
COUNT(*)
FROM
your_table
WHERE
created_at BETWEEN '2014-07-01' AND '2014-07-31 23:59:59'
GROUP BY
(DAYOFMONTH(created_at) - 1) DIV 3
Explanation:
With the help of the DIV operator you get your 3-day-slots.
Note
If there's a slot without rows, it won't be in the result. To get these too, you could use a LEFT JOIN with the maximum 11 slots.
Demo
If you having timestamps as attribute type then might be this help you
SELECT count(*) as count
FROM table
AND
TIMESTAMPDIFF(DAY,date,2014-08-01)<=3";
The date is the attribute of your column, TIMESTAMPDIFF will find difference between given date if it's under 3 days from 2014-08-01 records will show up. This way by just sending one date into this position you can find 3 slots of date from your table.
I am trying to create an event calendar with recurring events (ex. weekly or monthly) but I cannot wrap my head around it. Can anyone give me some pointers? What is the best way to go about doing this? Any help is greatly appreciated. Thanks.
Create three tables with a structure like:
event table
-id
-schedule_type
-schedule_id
-title
etc.
schedule table
-id
-event_id
-datetime
schedule_recurring table
-id
-event_id
-date
-time
In your event table, the schedule_type field will be either 0 or 1, which would indicate to the application which table the scheduling information is stored in, as well as how to interpret that information.
A non-recurring event will be stored in schedule with a datetime: 2011-09-06 00:00:00, and recurring events will be stored in schedule_recurring with a date: 'every 1st Monday' and a time: 09:30,12:20 (If the event occurs twice on every first Monday of the month).
Maybe this will help get you started!
I know this is an old post but I was thinking the same thing too.
I like the persons solution about using multiple tables to do it, but in fact it can all be done from one table.
Create a table with the following data...
event_title
event_text
event_image
and_other_fields_about_event
recur_code (text)
recur_mode (integer)
start_date (date)
end_date (date)
recur_end_date (date)
recur_mode can have three states -
0 = no recurrence
1 = recurrence with end date
2 = ongoing with no end date (e.g. if you want to add something like 1st Jan as New Years Day)
recur_code would store either NULL or a code in it if the date recurs. The code that should be used there would be the PHP DateInterval code (i.e. P1Y for 1 year or P3M (3 months) or P7D (7 days), etc) - if you want to shrink the data a bit you could chop off the initial 'P' and add it back later as the initial 'P' is always going to be P, it stands for Period so "Period 3 Months" "Period 7 Days", etc.
Then when your retrieving data from the database - you retrieve all data with the following searches
( end_date >= CURDATE () ) OR ( ( recur_mode = 1 ) AND ( recur_end_date >= CURDATE () ) ) OR ( recur_mode = 2 )
(please note this isn't proper SQL - it's just a basic example of the or statement you'd need)
then once you've retrieved the data use PHP with a while loop and DateInterval to increase the start_date until you get to the next re-occurrence also making sure that if recur_mode is set to 1 the start date is not after the recur_end_date.
All done in one table - and also if you want an input form to put the code in then use a hidden field with the dateinterval value in whilst using various radio buttons to select the interval - then use jQuery onchange to update the hidden value with the new selector values.
I have a table which holds restaurant reservations. It just has an restaurant_id and a date column which specify the actual date (we are talking about whole day reservations).
I want to find out when is the next available weekend for a particular restaurant. A "weekend" is either Saturday or Sunday. If one of them is available, then we have an available weekend.
The query should, of course, consider the current time to calculate the next weekend.
Can anyone help?
Here's the table structure and data for the "dates" table which holds all reservations made so far:
id id_venue date
12 1 2011-04-22
13 1 2011-04-23
14 1 2011-04-24
15 1 2011-04-30
16 1 2011-05-07
17 1 2011-05-08
As you can see, the weekend of 23-24 is full, so the one of 7-8 May. What I need to find is the date of 2001-05-01 which is the first available Saturday OR Sunday after today's date.
I think the others are missing the question... They think your table may already be POPULATED with all weekends and some status as to open or not... My guess is that your table only HAS a record IF it is reserved... thus you need to find records that DO NOT EXIST AT ALL... based on some automated Look for dates...
This is a modification to another post I've done here
Although I didn't change the context of the query, I only put in the columns associated to YOUR table. I understand you are only going against a single venue table and so am I (actually). However, to understand the "JustDates" alias, this INNER PRE-QUERY is creating a dynamically populated table of ALL DATES by doing a Cartesian join against ANY other table.. in this case, your "Venue" table of reservations (I didn't see your actual table name reference explicitly, so you'll have to change that). So, this in essence creates a table of all dates starting from whatever "today" is and goes forward for 30 days (via limit), but could be 40, 50, 300 or as many as you need.. provided the "YourVenueTable" has at least as many records as days you want to test for. (same clarification in post this was derived from). This result set going out 30, 40 or however many days is pre-filtered for ONLY the given day of week of 1-Sunday or 7-Saturday... So it should return a result set of only Apr 23, Apr 24, Apr 30, May 1, May 7, May 8, May 14, May 15, May 21, May 28, etc.
So NOW you have a dynamically created result set of all possible days you are considering moving forward. Now, that gets joined to your actual Venue Reservations table and is filtered to ONLY return those DATES where it is NOT found for the id_venue you are concerned about. In your data example it WOULD find a match on Apr 23 and 24 and NOT return those records. Same with Apr 30... However, it WILL find that the record in the prequalifying list that includes May 1 will NOT find the date match in the venue table and thus include that as you are anticipating... It will then continue to skip May 7 and 8, then return May 14, 15, 21, 28, etc...
select JustDates.OpenDate
from
( select
#r:= date_add( #r, interval 1 day ) OpenDate
from
( select #r := current_date() ) vars,
Venue
LIMIT 30 ) JustDates
where
DAYOFWEEK( JustDates.OpenDate ) IN ( 1, 7 )
AND JustDates.OpenDate NOT IN
( select Venue.date
from Venue
where Venue.id_venue = IDYouAreInterestedIn
and Venue.Date = JustDates.OpenDate )
order by
JustDates.OpenDate
Note, and per the other reservations posting, the query for reservation date availability dates doing a limit of 30 above can be ANY table in the system as long as it has AT LEAST as many days out as you want to look forward for reservations... If you want all availability for an upcoming year, you would want 365 records in the table used for a Cartesian result to get the #r cycling through dynamically created "date" records.
SELECT ...... DAYOFWEEK(`date`) as `num` FROM .... WHERE num = 1 OR num = 7
I don't know how u wanna check "availability"
How about?:
SELECT * FROM table WHERE (DAYOFWEEK(date)=1 OR DAYOFWEEK(date)=7) AND restaurant_id =$RESTAURANTID AND date > CURDATE() ORDER BY date ASC LIMIT 1
Set the number of days from today until the next Saterday (if 0 then today is Saterday)
Assuming that if today is Sunday you only want reservations for the next full weekend.
select #OffsetSaterday:= mod((8-DayOfWeek(CurDate())+7,7);
You have not supplied enough info to know how the reservation database looks, so I'm going to guess here.
Every restaurant has seats:
Table seats
id: integer primary key
rest_id: integer #link to restaurant
desc: varchar(20) # description of the seat.
Table restaurant
id: integer primary key
other fields.....
Table Reservation
id: integer primary key
reservation_date: date
seat_id: integer
The select statement to get all available seats for next weekend is:
select #OffsetSaterday:= mod((8-DayOfWeek(CurDate())+7,7);
select s.*, rst.* from seats s
inner join restaurant rst on (rst.id = seats.rest_id)
left join r on (r.seat_id = s.id
and r.reservation_date between
date_add(curdate(),interval #OffsetSaterday day) and
date_add(curdate(),interval #OffsetSaterday+1 day)
where r.id is null
order by s.rest_id, s.desc;
You might be able to combine the two selects into one, but MySQL does not guarantee the order in which expressions get evaluated, so I would recommend against that.