Ive got a simple query that is used on a search. My problem is with this query is that as the records in mysql are added everytime there is a transaction, the query returns a list of data when there could only be one or a few more rows instead of a lot more.
SQLFliddle
As you can see here - the query returns a lot of rows, where I want it to return
BLSH103 A001A 31 24/01/2014
Can the qty where the product name & pallet space are the same be summed? And then show the largest date?
just use a sum function on t.Quantity (and a group by clause)
SELECT (t.ProductName) as Pname ,(s.PalletSpace) as PSpace, sum(t.Quantity) as Qty,(t.TransactionDate) as Transac
FROM PalletSpaces s
JOIN ProductTrans t
ON s.PalletSpaceID = t.PalletSpace
WHERE t.ProductName LIKE 'BLSH103' OR s.PalletSpace LIKE 'BLSH103'
group by
Pname,
pSpace,
Transac -- if you want to group by date also...
By the way, using LIKE this way (without %) doesn't make much sense...
see SqlFiddle
You just need to use GROUP BY and SUM in this way:
SELECT (t.ProductName) as Pname ,(s.PalletSpace) as PSpace, SUM(t.Quantity) as Qty,(t.TransactionDate) as Transac
FROM PalletSpaces s
JOIN ProductTrans t
ON s.PalletSpaceID = t.PalletSpace
WHERE t.ProductName LIKE 'BLSH103' OR s.PalletSpace LIKE 'BLSH103'
GROUP BY t.ProductName, s.PalletSpace;
Related
Each page in my system has multiple page_objects.
I need to return the last_changed records of my page_objects per page.
To decrease DB-impact, I have a SELECT ... IN query to return each last-edited page_object per page:
SELECT object, f_page_id, page_object_id, last_change
FROM page_objects
WHERE f_page_id IN (page_id1, page_id2, page_id3, etc...) GROUP BY f_page_id
ORDER BY last_change ASC;
Of course this does not work, because GROUP BY is applied before ORDER BY, so I changed the query:
SELECT object, f_page_id, page_object_id, max(UNIX_TIMESTAMP(last_change))
FROM page_objects
WHERE f_page_id IN (page_id1, page_id2, page_id3, etc...) GROUP BY f_page_id
But this still does not return the last-edited page_object per page_id.
What am I doing wrong?
Your query does not specify to get the record for the latest last_change. Merely that it gets the latest value of last_change. The other non aggregate values (ie, not the result of an aggregate function like MAX or MIN) that are not mentioned in the GROUP BY clause can come from any row for the grouped values.
As such you use a sub query to get the latest value for each page, and then join that back against your main table to get the matching rows
Something like this:-
SELECT page_objects.object,
page_objects.f_page_id,
page_objects.page_object_id,
page_objects.last_change
FROM page_objects
INNER JOIN
(
SELECT f_page_id, MAX(last_change) AS latest_last_change
FROM page_objects
GROUP BY f_page_id
) sub0
ON page_objects.f_page_id = sub0.f_page_id
AND page_objects.last_change = sub0.latest_last_change
WHERE page_objects.f_page_id IN (page_id1, page_id2, page_id3, etc...)
ORDER BY last_change DESC
Note that MySQL is quite unusual at allowing you to have non aggregate columns that are not mentioned in the GROUP BY clause (as it is against SQL standards, except under very particular circumstances). Most flavours of SQL will issue an error if you try this, and MySQL has a configuration parameter which will similar cause it to reject such queries.
I am trying to build an access query with multiple criteria. The table to be queried is "tblVendor" which has information about vendor shipment data as shown below:
The second table is "tblSchedule" which has the schedule for each Vendor cutoff date. This table has cutoff dates for data analysis.
For each vendor, I need to select records which have the ShipDate >= CutoffDate. Although not shown in the data here, it may be possible that multiple vendors have same CutoffDate.
For small number of records in "tblCutoffdate", I can write a query which looks like:
SELECT tblVendors.ShipmentId, tblVendors.VendorNumber, tblVendors.VendorName,
tblVendors.Units, tblVendors.ShipDate
FROM tblVendors INNER JOIN tblCutoffDate ON tblVendors.VendorNumber =
tblCutoffDate.VendorNumber
WHERE (((tblVendors.VendorNumber) In (SELECT VendorNumber FROM [tblCutoffDate] WHERE
[tblCutoffDate].[CutoffDate] = #2/1/2014#)) AND ((tblVendors.ShipDate)>=#2/1/2014#)) OR
(((tblVendors.VendorNumber) In (SELECT VendorNumber FROM [tblCutoffDate] WHERE
[tblCutoffDate].[CutoffDate] = #4/1/2014#)) AND ((tblVendors.ShipDate)>=#4/1/2014#));
As desired, the query gives me a result which looks like:
What concerns me now is that I have a lot of records being added to the "tblCutoffDate" which makes it difficult for me to hardcode the dates in the query. Is there a better way to write the above SQL statement without any hardcoding?
You might try something like -- this should handle vendors having no past cutoff,
or those having no future cutoff
"today" needs a suitable conversion to just date w/o time
comparison "=" may go on both, or one, or none Max/Min
"null" may be replaced by 1/1/1900 and 12/31/3999 in Max/Min
SELECT tblvendors.shipmentid,
tblvendors.vendornumber,
tblvendors.vendorname,
tblvendors.units,
tblvendors.shipdate
FROM tblvendors
LEFT JOIN
( SELECT vendornum,
Max( iif cutoffdate < today, cutoffdate, null) as PriorCutoff,
Min( iif cutoffdate >= today, cutoffdate, null) as NextCutoff
FROM tblcutoffdate
GROUP BY vendornum
) as VDates
ON vendornumber = vendornum
WHERE tblvendors.shipdate BETWEEN PriorCutoff and NextCutoff
ORDER BY vendornumber, shipdate, shipmentid
A simpler WHERE clause should give you what you want.
SELECT
v.ShipmentId,
v.VendorNumber,
v.VendorName,
v.Units,
v.ShipDate
FROM
tblVendors AS v
INNER JOIN tblCutoffDate AS cd
ON v.VendorNumber = cd.VendorNumber
WHERE v.ShipDate >= cd.CutoffDate;
I have the following query:
SELECT routes.route_date, time_slots.name, time_slots.openings, time_slots.appointments
FROM routes
INNER JOIN time_slots ON routes.route_id = time_slots.route_id
WHERE route_date
BETWEEN 20140109
AND 20140115
AND time_slots.openings > time_slots.appointments
ORDER BY route_date, name
This works just fine and will produce the following results:
What I want to do is only return one name per date. So the 9th, name = 1, would only have 1 result, rather than 2, as it currently does.
UPDATE: See the SQLFIDDLE for different type of solutions here: http://sqlfiddle.com/#!2/9ac65b/6
Will it solve your request if you use...
SELECT DISTINCT routes.route_date...your query... ?
It depends if you know that your rows always will have the same values, for same date/name.
Otherwise use group by...
(which I think suits your request best)
SELECT routes.route_date, time_slots.name, sum(time_slots.openings), sum(time_slots.appointments)
FROM routes
INNER JOIN time_slots ON routes.route_id = time_slots.route_id
WHERE route_date
BETWEEN 20140109
AND 20140115
AND time_slots.openings > time_slots.appointments
group by routes.route_date, time_slots.name
ORDER BY route_date, name
(i did a sum for the openings and appointments, you could do min, max, count, etc. Pick the one that fits your requirements best!)
You need to figure out which "name" you want when there are several for the same date.
Then you can group by date and select the right "name" by using an aggregate function like COUNT, MAX, etc.
I can't help you more if you don't explain your rule for picking one.
I want to count how many records from another table in the same select statement , i used Left join
and in the select statement i put count(ag.*)
see the
Example :
$q = Doctrine_Query::create()
->select("a.answer_id,a.date_added , count(ag.content_id) AS agree_count")
->from('Answer a')
->leftJoin("a.Agree ag ON a.answer_id = ag.content_id AND ag.content_type = 'answer' ")
->where('a.question_id= ? ', $questionId)
But its only returning the first record, can i Fix that? or to make another table and make it only for counting ?
You are missing a GROUP BY in your query.
More infos here.
When you don't have a GROUP BY clause, it's normal to get only one row.
Count(*) will only return one record if you don't use Group By. You are asking it to count all the records, so there can be only one result.
The count() SQL function changes how results are returned from the database - without a GROUP BY the database will only return one record, regardless of other colums in the SELECT.
if you add:
group by a.answer_id
to the end of your SQL query, that might DWYM.
MySQL Server Version: Server version: 4.1.14
MySQL client version: 3.23.49
Tables under discussion: ads_list and ads_cate.
Table Relationship: ads_cate has many ads_list.
Keyed by: ads_cate.id = ads_list.Category.
I am not sure what is going on here, but I am trying to use COUNT() in a simple agreggate query, and I get blank output.
Here is a simple example, this returns expected results:
$queryCats = "SELECT id, cateName FROM ads_cate ORDER BY cateName";
But if I modify it to add the COUNT() and the other query data I get no array return w/ print_r() (no results)?
$queryCats = "SELECT ads_cate.cateName, ads_list.COUNT(ads_cate.id),
FROM ads_cate INNER JOIN ads_list
ON ads_cate.id = ads_list.category
GROUP BY cateName ORDER BY cateName";
Ultimately, I am trying to get a count of ad_list items in each category.
Is there a MySQL version conflict on what I am trying to do here?
NOTE: I spent some time breaking this down, item by item and the COUNT() seems to cause the array() to disappear. And the the JOIN seemed to do the same thing... It does not help I am developing this on a Yahoo server with no access to the php or mysql error settings.
I think your COUNT syntax is wrong. It should be:
COUNT(ads_cate.id)
or
COUNT(ads_list.id)
depending on what you are counting.
Count is an aggregate. means ever return result set at least one
here you be try count ads_list.id not null but that wrong. how say Myke Count(ads_cate.id) or Count(ads_list.id) is better approach
you have inner join ads_cate.id = ads_list.category so Count(ads_cate.id) or COUNT(ads_list.id) is not necessary just count(*)
now if you dont want null add having
only match
SELECT ads_cate.cateName, COUNT(*),
FROM ads_cate INNER JOIN ads_list
ON ads_cate.id = ads_list.category
GROUP BY cateName
having not count(*) is null
ORDER BY cateName
all
SELECT ads_cate.cateName, IFNULL(COUNT(*),0),
FROM ads_cate LEFT JOIN ads_list
ON ads_cate.id = ads_list.category
GROUP BY cateName
ORDER BY cateName
Did you try:
$queryCats = "SELECT ads_cate.cateName, COUNT(ads_cate.id)
FROM ads_cate
JOIN ads_list ON ads_cate.id = ads_list.category
GROUP BY ads_cate.cateName";
I am guessing that you need the category to be in the list, in that case the query here should work. Try it without the ORDER BY first.
You were probably getting errors. Check your server logs.
Also, see what happens when you try this:
SELECT COUNT(*), category
FROM ads_list
GROUP BY category
Your array is empty or disappear because your query has errors:
there should be no comma before the FROM
the "ads_list." prefix before COUNT is incorrect
Please try running that query directly in MySQL and you'll see the errors. Or try echoing the output using mysql_error().
Now, some other points related to your query:
there is no need to do ORDER BY because GROUP BY by default sorts on the grouped column
you are doing a count on the wrong column that will always give you 1
Perhaps you are trying to retrieve the count of ads_list per ads_cate? This might be your query then:
SELECT `ads_cate`.`cateName`, COUNT(`ads_list`.`category`) `cnt_ads_list`
FROM `ads_cate`
INNER JOIN `ads_list` ON `ads_cate`.`id` = `ads_list`.`category`
GROUP BY `cateName`;
Hope it helps?