I have a couple of Tables sor_added and sor_unsold, I am looking to calculate the stock that has been sold in an outlet. The stock is added and topped up to a certain quantity (not necessary for the purpose of this), and I will record the stock that has not been sold (unsold). Therefore I add the stock on a certain week and count up sales either a week or several weeks later.
With the following code I can workout what has been sold when I visit every week
SELECT week(A.datestamp) As Week_No, A.storename, A.product, SUM(A.qty - U.qty) As Sold_Qty
FROM sor_added A
JOIN sor_unsold U on U.storename = A.storename AND U.product = A.product AND WEEK(U.datestamp)-1 = WEEK(A.datestamp)
GROUP BY WEEK(A.datestamp), A.storename, A.product
And the only slightly tweaked code if I visit every three weeks:
SELECT week(A.datestamp) As Week_No, A.storename, A.product, SUM(A.qty - U.qty) As Sold_Qty
FROM sor_added A
JOIN sor_unsold U on U.storename = A.storename AND U.product = A.product AND WEEK(U.datestamp)-3 = WEEK(A.datestamp)
GROUP BY WEEK(A.datestamp), A.storename, A.product
I have tried integrating this and version of it but to no avail.
SELECT *
FROM sor_added
WHERE Datestamp = ( SELECT MAX(Datestamp)
FROM sor_added
WHERE Datestamp < ( SELECT MAX(Datestamp)
FROM sor_added
)
)
Despite trying to add this sub query to replace the WEEK - X I seem to lose my way and ruin my query... How would I write and implement SQL that would figure out how many weeks since I last visited the store in question?
Related
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
I have two tables requisition_headers and order_headers. I am interested in finding the average time it takes from the time the requisition is submitted (requisition_headers.submitted_at) and the time the order is created (orders.headers_created_at) where the requisition_headers.status <> 'draft'.
I would like the result to look like:
Avg_Req_To_PO_Cycle_Time = 3.2 Days
I have the following script but it's not working:
SELECT Database() as Customer,
AVG(timestampdiff(requisition_headers.submitted_at,order_headers.created_at)) AS REQ_PO_Cycle_Time
FROM order_headers
LEFT JOIN requisition_headers ON order_headers.requisition_header_id = requisition_headers.id
WHERE requisition_headers.status <> 'draft'
Any Ideas?
--UPDATE--
I changed the query to the following and now get a response of 229491.71 my question is- is that days, hours, minutes, seconds?
SELECT DATABASE() AS CUSTOMER,
AVG(TIME_TO_SEC(TIMEDIFF(order_headers.created_at,requisition_headers.submitted_at))) as Cycle_time
FROM order_headers LEFT JOIN requisition_headers ON order_headers.requisition_header_id = requisition_headers.id
where requisition_headers.status <> 'draft'
Make sure you know what a system function returns when you use it. The TimestampDiff function returns the difference between the two dates in the unit you specify in the first argument. You don't specify that unit so I don't know what you get back. I get a compile error.
In your second attempt, you are using TimeDiff which returns an interval value, then converting the result of Avg to seconds. So if you want the result in fractional days just divide by the number of seconds in a day.
You also use a left join when getting the dates. At first I thought you wanted to get all the requisitions whether the orders had been created or not. But you are joining the tables in the wrong order for that. But, assuming that is your intention, if the order has not yet been created you will be putting NULL as one of the parameters. You will get a NULL as an answer so you get nothing. If you want to use a left join, then you should specify a substitute date for any missing Created dates -- after getting the table in the right order, that is.
Here are two options. One ignores orders that have not yet been created by using a regular inner join. The other includes those but substitutes the current date and time.
By asking for the number of minutes between the dates, the final answer in days is found by dividing by the number of minutes in a day.
SQLFiddle
SELECT Customer,
AVG( timestampdiff( minute, r.submitted_at,
o.created_at)) / (24 * 60 )AS REQ_PO_Cycle_Time
FROM requisition_headers r
JOIN order_headers o
ON o.requisition_header_id = r.id
WHERE r.status <> 'draft'
group by Customer;
SELECT Customer,
AVG( timestampdiff( minute, r.submitted_at,
IfNull( o.created_at, CurDate()))) / (24 * 60 )AS REQ_PO_Cycle_Time
FROM requisition_headers r
LEFT JOIN order_headers o
ON o.requisition_header_id = r.id
WHERE r.status <> 'draft'
group by Customer;
I have this query wherein I want to find out the sales for the current year and the sales for last year. I cannot make it into 2 separate queries since it has to be of the same item code. Meaning the item codes used in the sales for the current year must also be the item codes used for the sales last year.
The code below is working but it takes almost 8 to 9 minutes to fetch
select p.itemcode,
p.itemdescription,
( select round((SUM(SA.QUANTITY*P.SellingPrice)),2)
from sales s
join product p on s.itemcode=p.itemcode
where YEAR(s.date) = 2013
),
( select round((SUM(SA.QUANTITY * P.SellingPrice)),2)
from sales s
join product p on s.itemcode=p.itemcode
where YEAR(s.date) = 2012
)
from product p
join supplier s on p.suppliercode = s.suppliercode
join currency c on c.countrycode=s.countrycode
join country co on co.countrycode=c.countrycode
JOIN SALES SA ON SA.ITEMCODE=P.ITEMCODE
where c.countrycode = 'NZ'
group by p.itemcode
limit 10
Ideally the output should be
Itemcode Itemdescription SalesforCurrentYear SalesforLastYear
GS771516 BUBBLE PARTY MACHINE 1035300.00 2079300.00
GSNBC-025 X'MAS HOUSE 600612.25 1397163.25
GSNBC-031 BRANDENBURGER TOR 741010.75 1572207.25
Thanks!!
The query can be simplified by eliminating two joins:
select .......
.......
from product p
join supplier s on p.suppliercode = s.suppliercode
JOIN SALES SA ON SA.ITEMCODE=P.ITEMCODE
where s.countrycode = 'NZ'
group by p.itemcode
limit 10
Afterwards, two dependent subqueries in the select clause can be reduced to one outer join:
select p.itemcode,
p.itemdescription,
round((SUM( CASE WHEN YEAR(s.date) = 2013
THEN SA.QUANTITY*P.SellingPrice
ELSE 0 END
)),2) As Sum2013,
round((SUM( CASE WHEN YEAR(s.date) = 2012
THEN SA.QUANTITY * P.SellingPrice
ELSE 0 END
)),2) As Sum2012
from product p
join supplier s on p.suppliercode = s.suppliercode
LEFT JOIN SALES SA ON SA.ITEMCODE=P.ITEMCODE
where s.countrycode = 'NZ'
group by p.itemcode
limit 10
Please try this query and let us know how it will perform.
Follow any of these steps
1.You can parse your query.
2.Remove redundant statements.
3.Use inner join or outer join.
You've got sales three times in the same scope. I'd get rid of two of those, and that should help. Also, in terms of business logic, all of these tables seem mandatory for a sale. If that's true, you should use "inner join", for compatibility with standard SQL - even though it's the same in MySQL.
I'm attempting to condense several SQL calls into one, and wanted to know if the following were possible.
Here are are my tables.
Organization
id
Event
id,
startDate
endDate
FavoriteOrgs
userId
orgId
For each day of the month, I want to return a count of the events occurring on that day. Not too difficult, until you add the fact that events can span 2 or 3 days.
Here's what I have so far, which accurately shows event counts by day, but it only includes the event in count for the day it begins.
SELECT DAYOFMONTH( CAST( o.start_date AS DATE ) ) AS dayNum, COUNT( * ) AS count
FROM favoriteOrgs f, event e, organization o
WHERE f.user_id =200372
AND e.profile_id = o.id AND e.profile_id = f.profile_id AND o.id = f.profile_id
AND e.last_date >= '$startDate'
AND e.start_date <= '$lastDate'
GROUP BY e.start_date
Your data model isn't actually modeling all of the entities in your system. One entity is the dates for which you are interested in reporting things.
You should add a table to your database (or use a temporary table, inline table, or whatever else is available with MySQL). The table is simply all of the relevant dates. Even a table that goes back to 1900 and forward to 2100 is going to be fairly small.
The query then becomes trivial:
CREATE TABLE Calendar (
calendar_date DATE NOT NULL,
CONSTRAINT PK_Calendar PRIMARY KEY CLUSTERED
)
SELECT
C.calendar_date,
COUNT(*) AS count
FROM
favoriteOrgs F
INNER JOIN Event E ON
E.profile_id = F.profile_id AND
E.last_date >= '$startDate' AND
E.start_date <= '$lastDate'
INNER JOIN Organization O ON
O.id = F.profile_id AND
O.id = E.profile_id
WHERE
F.user_id = 200372
GROUP BY
C.calendar_date
You also now have an advantage that you can add additional business specific information to calendar dates, like an "is_holiday" column, "economic_quarter" or whatever. Just remember to prefill the table, which is a simple loop that you have to run once.
I have a theme gallery. In the dashboard i have to display the most viewed themes BY date (today, last 7 days, last 30 days, all time).
These are the 2 involved tables:
theme
id_theme
title
views
id_view
id_theme
date
The $timestamp values are calculated with mktime() (no prob in there).
This is my current SQL query:
SELECT t.id_theme,t.title,
(SELECT COUNT(*)
FROM views
WHERE views.id_theme=t.id_theme
AND views.date BETWEEN '.$timestamp1.' AND '.$timestamp2.')
AS q
FROM theme AS t
INNER JOIN views ON t.id_theme = views.id_theme
GROUP BY views.id_theme
ORDER BY q
DESC LIMIT 10
The problem is that The catch, is that sometimes it receives themes with 0 views, and that should not happen. I tried changing the INNER JOIN with RIGHT JOIN with no results. Any ideas?
Hmm. not sure why you're using subqueries for this, seems like this would work better:
SELECT theme.id_theme, theme.title, COUNT(views.id_view) as view_count
FROM theme
LEFT JOIN views ON (theme.id_theme = views.id_theme)
GROUP BY theme.id_theme
WHERE views.date > DATE_SUB(now() INTERVAL 30 day)
ORDER BY view_count DESC
HAVING view_count > 0
SELECT t.id_theme, t.title, COUNT(*) AS q
FROM theme AS t
INNER JOIN views ON t.id_theme = views.id_theme
AND views.date BETWEEN '.$timestamp1.' AND '.$timestamp2.'
GROUP BY t.id_theme, t.title
ORDER BY q
DESC LIMIT 10