Select distinct shou - mysql

I'm stuck with this problem for days and still can't think of a solution.Maybe i'm just making it too complex.
So my query looks like this.
SELECT distinct Cast(Table1.Date as Date) AS 'Date', Concat(Round(SUM((ISNULL(Price.Morning,0) + ISNULL(Price.Day,0) + ISNULL(Price.Evening,0))*Tickets.Count),2),' €') AS 'Total'
FROM Price,Tickets,Table1
WHERE Tickets.Price_ID = Price.Price_ID AND
Tickets.Table1_ID = Table1.Table1_ID
GROUP BY Date
;
The query should display distinct dates and total SUM should be displayed that was earned in the specific date.
As you can see there still are matching dates
EDIT. I don't know if i understood the criticism correctly but i applied these changes.
SELECT distinct Cast(Tabl1.Date as Date) AS 'Date', Concat(Round(SUM((ISNULL(Price.Morning,0) + ISNULL(Price.Day,0) + ISNULL(Price.Evening,0))*Tickets.Count),2),' €') AS 'Total'
FROM Table1
JOIN Tickets ON Tickets.Table1_ID = Table1.Table1_ID
JOIN Price ON Tickets.Price_ID = Price.Price_ID
GROUP BY Date
;
And i also understand that i need to provide more information for solution.
All the ..Concat(Round(SUM((ISNULL(Price.Morning,0) + ISNULL(Price.Day,0) + ISNULL(Price.Evening,0))*Tickets.Count),2),' €') AS 'Total' .. Is necessary because in the database there are Null values, thatš why there i use ISNULL function and 0 in case it is NULL because otherwise it brakes all the calculations.You can see that table here: I edited the column names so you could see(table itself is in different language)
(The column without name is not required for this)

Use explicit join not coma separated old join method and use subquery for format of total . No need distinct
select 'Date', concat(total,' €') from
(
SELECT Cast(Table1.Date as Date) AS 'Date',
SUM(Price.Morning+Price.Day+Price.Evening) as total
FROM Price join
Tickets on Tickets.Price_ID = Price.Price_ID
join Table1 on Tickets.Table1_ID = Table1.Table1_ID
GROUP BY Date
) as t

Related

MySQL: Update with nested subquery

I'm trying to make this query work. The aim is to get the minimum date between a list of minimum dates.
But I'm getting: Unknown column 'di.device_id' in 'where clause'
How can I expose the device_id field to be visible inside the second subquery?
update device_information di
set first_seen=(
select min(date) from (
select min(insert_date) date from product_state_change_event where device_id=di.device_id
union select min(insert_date) date from sensor_range_switch_change_event where device_id=di.device_id
) as dates
);
Edited
In fact, I have 19 tables to union them.
I would expect a query such as this:
update device_information di join
(select min(insert_date) as minid
from product_state_change_event psce
group by psce.device_id
) psce
on psce.device_id = di.device_id
set first_seen = least(psce.insert_date, psce.minid);
This assumes that the dates are never NULL. That is easily incorporated into the answer (by adding more logic to the least()).
If anyone want to know how I solved it:
update device_information di
join (
select identifier, min(date) date from (
select client_var_name identifier, min(insert_date) date from product_state_change_event group by client_var_name
union all select client_var_name identifier, min(insert_date) date from sensor_range_switch_change_event group by client_var_name
...
) as unique_dates group by identifier
) as dates on di.identifier = dates.identifier
set di.first_seen = dates.date;

return MIN(DATE) and other existing date

I want to return all the minimum dates of every single clients in the table and display it as "FIRST" if it is the MIN date, and IF its not, it will return "OTHER"
this is my query
SELECT TRANS_DATE, IF(TRANS_DATE= MIN(TRANS_DATE), 'FIRST', 'OTHER') AS TR_CODE
FROM `posthis`
WHERE datepost IS NOT NULL
My query only returns the MIN()
this is the result that I need
CLIENTID TRANS_DATE TR_CODE
02-00002234 2002-02-01 FIRST
02-00002234 2002-02-02 OTHER
02-00002234 2002-02-03 OTHER
02-00002235 2003-01-03 FIRST
02-00002235 2003-01-05 OTHER
02-00002235 2003-01-06 OTHER
02-00002236 2003-01-03 FIRST
02-00002236 2003-01-04 OTHER
02-00002236 2003-01-13 OTHER
Using MIN() as an analytic function would really come in handy for your problem. But since MySQL does not support this, we can use a join instead. In the query below, I LEFT JOIN the posthis table to a subquery which identifies the earliest date for each client. Should a record in posthis match to this subquery, we label it with a code 'FIRST', otherwise we label 'OTHER'.
SELECT
t1.CLIENTID,
t1.TRANS_DATE,
CASE WHEN t2.CLIENTID IS NOT NULL THEN 'FIRST' ELSE 'OTHER' END AS TR_CODE
FROM posthis t1
LEFT JOIN
(
SELECT CLIENTID, MIN(TRANS_DATE) AS MIN_TRANS_DATE
FROM posthis
GROUP BY CLIENTID
) t2
ON t1.CLIENTID = t2.CLIENTID AND
t1.TRANS_DATE = t2.MIN_TRANS_DATE

Display zero in group by sql for a particular period

I am trying to run the following query to obtain the sales for each type of job for a particular period. However for certain months where there are no jobs of a particular job type performed no 0 is displayed in sales.
How can i display the zeros in such a condition.
Here is the sql query-
select Year(postedOn), month(postedOn), jobType, sum(price)
from tbl_jobs
group by jobType, year(postedOn), month(postedOn)
order by jobType, year(postedOn), month(postedOn)
Typically, this is where your all-purpose calendar or numbers table comes in to anchor the query with a consistent sequential set:
SELECT job_summary.*
FROM Calendar
CROSS JOIN (
-- you may not have though about this part of the problem, though
-- what about years/months with missing job types?
SELECT distinct jobType FROM tbl_jobs
) AS job_types
LEFT JOIN (
select Year(postedOn) AS year,month(postedOn) as month,jobType ,sum(price)
from tbl_jobs
group by jobType, year(postedOn), month(postedOn)
) job_summary
ON job_summary.jobType = job_types.jobType
AND job_summary.year = Calendar.year
AND job_summary.month = Calendar.month
WHERE Calendar.day = 1 -- Assuming your calendar is every day
AND calendar.date BETWEEN some_range_goes_here -- you don't want all time, right?
order by job_types.jobType, Calendar.year, Calendar.month

mySQL two tables LEFT JOIN on multiple NULLS

I have a question regarding a two table join. In this case Table1 (booking table) and Table2 (Booking Entries).
I need a query to get all the rows from Table1 WHERE the member_id in Table2 (exists only here not in table1) and Vip_id in BOTH tables can be searched.
SELECT vb.* , DATE_FORMAT(vb.bookingdate, '%W %D %M') bookingdate, DATE_FORMAT(vb.bookingrsvp, '%W %D %M') bookingrsvp, concat(sl.state, ' - ', sl.store) store, sl.ADD1, sl.ADD2, sl.SUBURB, sl.PHONE , ve.vip_entry_leadid
FROM vip_booking vb
INNER JOIN storelocator sl ON (vb.storeid = sl.id )
LEFT JOIN vip_entries ve ON (vb.vipid = ve.vip_id AND ve.vip_entry_leadid = '" . $_GET["leadid"] . "')
WHERE vb.vipid = " . $_GET["vipid"] . "
AND DATE(vb.bookingdate) >= CURDATE()
AND ve.vip_entry_leadid IS NULL
AND ve.vip_id IS NULL
GROUP BY vb.storeid ORDER BY sl.state, sl.store
Basically what I am trying to achieve here is select ALL bookings from ALL Stores part of a particular VIP EVENT that the CURRENT LOGGED IN USER hasn't already had an entry too? If it was a single field ie. vip_entries.vip_id = vip_booking.vipid THEN that would be okm however a user can be in the entries table multiple times provided that it is a DIFFERENT event?
The above query works however I don't know if I have written it correctly as I would like to use joins and avoid sub-queries.
Can you post some sample data in the question please.
Your query appears to do a LEFT JOIN on vip_entries, and then checks for NULL in 2 fields to ensure no record is found (might be better to check the unique id field of vip_entries, if one exists). But you then bring back the value vip_entries.vip_entry_leadid which will always be null.
Further you are using GROUP BY store_id. This will bring back one row per store_id, but the other values will be from an undefined row for that store_id (in most databases this would fail). I suspect looking at your description you actually want to bring back one row per event / store id (which is probably a unique combination) in which case it would seem you do not need the GROUP BY.
The above query works however I don't know if I have written it correctly
Unfortunately, while preceding SQL works in MySQL, your query is not valid in ANSI SQL. Only GROUP BY column and aggregation function can be SELECTed
I would like to use joins and avoid sub-queries.
As far as I know without sub-queries, you can only fetch vb.storeid as follows
SELECT vb.storeid
FROM vip_booking vb
INNER JOIN storelocator sl ON (vb.storeid = sl.id )
LEFT JOIN vip_entries ve ON (vb.vipid = ve.vip_id AND ve.vip_entry_leadid = '$leadid')
WHERE vb.vipid = $vipid
AND DATE(vb.bookingdate) >= CURDATE()
AND ve.vip_entry_leadid IS NULL
AND ve.vip_id IS NULL
GROUP BY vb.storeid;
Proper SQL with sub-queries:
In my opinion Following query is formal SQL for what you want.
SELECT
vb.*,
DATE_FORMAT(vb.bookingdate, '%W %D %M') bookingdate,
DATE_FORMAT(vb.bookingrsvp, '%W %D %M') bookingrsvp,
CONCAT(sl.state, ' - ', sl.store) store,
sl.ADD1, sl.ADD2, sl.SUBURB, sl.PHONE , ve.vip_entry_leadid
FROM
(SELECT DISTINCT
vb.storeid
FROM
vip_booking vb
LEFT JOIN
vip_entries ve ON (vb.vipid = ve.vip_id AND ve.vip_entry_leadid = '" . $_GET["leadid"] . "'
WHERE
vb.vipid = " . $_GET["vipid"] . "
AND DATE(vb.bookingdate) >= CURDATE()
AND ve.vip_entry_leadid IS NULL
AND ve.vip_id IS NULL) x
INNER JOIN
storelocator sl ON (x.storeid = sl.id)
ORDER BY
sl.state, sl.store;

MySQL Group By Date for NULL values

I am trying to return the number of orders for every day a commerce site has been live, but for days where there were 0 orders my sql statement returns null, and hence their is a gap in the data. How can I insert a 0 into these days so the data is complete?
$sql = "SELECT COUNT(*) AS orders
FROM `orders`
GROUP BY DATE(`order_datetime`)
ORDER BY DATE(`order_time`) ASC";
$query = $this->db->query($sql);
I have tried using ifnull like so but I get the same result as above:
$sql = "SELECT ifnull(COUNT(*),0) AS orders
FROM `orders`
GROUP BY DATE(`order_datetime`)
ORDER BY DATE(`order_time`) ASC";
$query = $this->db->query($sql);
can you use COALESCE?
eg:
SELECT COALESCE(COUNT(*),0) AS orders
FROM `orders`
GROUP BY DATE(`order_datetime`)
ORDER BY DATE(`order_time`) ASC
it returns first non null value in the list - count if its not null and 0 if it is.
http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#function_coalesce
hang on.. is the issue that there are no rows with those dates so you just get results for those dates?
if so you could return the order date too and be a bit more clever about how you display your result:
SELECT order_datetime,COUNT(*) AS orders
FROM `orders`
GROUP BY DATE(`order_datetime`)
ORDER BY DATE(`order_time`) ASC
then when outputting your results maybe create a loop that iterates through the dates you are interested in and prints a 0 if there is no row for that date:
for (datetime d = startdate; d <= enddate; datetime.adddays(1)){
if (recordset[order_datetime] == d){
output (d,recordset[orders]);
recordset.movenext();
}else
{
output (d,0);
}
}
(note i have no idea what programming language that would be ;-)
if you want to do it all in the DB then look at this SO question for how to create a table of the dates on the fly and then you can left outer join from it to you query on date..
Get a list of dates between two dates
You should select all the dates you want manually in a sub-query and LEFT JOIN it with your table:
SELECT COUNT(*) AS orders FROM
( SELECT '2010-09-01' AS date UNION SELECT '2010-09-02' UNION
SELECT '2010-09-03' UNION SELECT '2010-09-04' UNION SELECT '2010-09-05' UNION
SELECT '2010-09-06' UNION SELECT '2010-09-07' ... ) AS dates
LEFT JOIN orders ON( dates.date = orders.order_datetime )
GROUP BY orders.order_datetime
ORDER BY orders.order_datetime
or use you current query and fill the gaps in your php program after receiving the results.