Using two sets of conditions in where clause - mysql

I'm trying to get the count of items in my table where it should satisfy these conditions
status = active
type = Pre-order
date = $date_input
OR
status = active
type = Both
date = $date_input
I'm trying to use this statement but I'm pretty sure it's messed up.
SELECT COUNT(id) as count_date from date_restriction
where (date='$date_input' AND status='active' AND type='Pre-order')
OR (date='$date_input' AND status='active' AND type='Both')
I also tried this to no avail
SELECT COUNT(id) as count_date from date_restriction
where date='$date_input' AND status='active' AND type='Pre-order' OR type='Both'

Whe you have mixed AND and OR condition you need () for the or clause
SELECT COUNT(id) as count_date
from date_restriction
where date='$date_input'
AND status='active'
AND ( type='Pre-order' OR type='Both')
or instear of several or condition you could use a IN clause
AND type IN ('Pre-order', 'Both')
anyway you should avoid the use of php var in SQL you are at risk for sqlinjection .. for avoid this you should take a look at prepared statement and binding param for your db driver

Your code should work. I would write this as:
select count(*) as count_date
from date_restriction
where date = ? AND status = 'active' AND
type in ('Pre-order', 'Both');
Note: The ? is for a parameter so you are not munging the query string with input values.
If I had to guess why this isn't working, I would speculate that one or both of the dates have a time component. You might try:
where date(date) = date(?) . . .
to be sure you are matching on the date, regardless of time.

SELECT count(id) as count_date
FROM date_restriction
WHERE date='$date_input' AND status='active' AND (type='Pre-order' OR type='Both');
Here, date and status both fields are common in your case; hence, don't wrap it in parenthesis whereas, add OR condition for type field only and con-cat it with AND in WHERE clause.

Related

ORDER BY field when using table joins

I've got a products table that I'm trying to get to work. The query brings back results; however, it isn't actually using the ORDER BY FIELD to sort the results. It's skipping it somehow. I even tried ORDER BY FIELD(sc.id,'4','5','6'), and that didn't work either.
Is it even possible to use table_name.column in an ORDER BY FIELD()? Is there an alternative or a better method of doing this query?
$product = $db1q->query("
SELECT p.id, p.name, p.image, p.url,p.subcat as subcat, sc.id as scid,sc.name as scname
FROM Product as p
JOIN Product_Sub_Category as sc ON p.subcat = sc.id
WHERE p.visibility='1' AND find_in_set(p.id,'". $sidr['products'] ."')
ORDER BY FIELD(p.subcat,'4','5','6'), sc.sort_order ASC, p.sort_order ASC")
or die ('Unable to execute query. '. mysqli_error($db1q));
I just dumbed the query down to the basic level....
$product = $db1q->query("
SELECT id, name, image, url,subcat
FROM Product WHERE visibility='1' AND id IN ({$sidr['products']}) ORDER BY FIELD(subcat,'5','4','6','22')") or die ('Unable to execute query. '. mysqli_error($db1q));
and for some reason the order of my subcats are as follows....
3,12,23,5,5,4,4,4,4,4,22
Why wouldn't they begin with 5, 4, 6(doesn't exist), and 22? Then display 3,12, and 23 after those are first....
Simple Rextester Demo
When datatype is numeric don't compare to 'string' values
eg visibility = '1' if visibility is numeric you really shouldn't have the apostrophes around it. same in the field function given subcat.
$product = $db1q->query("SELECT id, name, image, url,subcat
FROM Product
WHERE visibility='1'
AND id IN ({$sidr['products']})
ORDER BY case when subcat in (5,4,6,22) then 0 else 1 end,
FIELD(subcat,5,4,6,22)
") or die ('Unable to execute query. '. mysqli_error($db1q));
or something like:
order by case when field(sort,'5','4','22') = 0 then (select max(sort)+1+sort from Product)
else field(sort,'5','4','22') end;
The issue with the 2nd approach is that it has to run a subquery for every record. In addition if the size of subcat/sort exceed or approach the max of int we'll run into a problem adding the values together. This problem is negated by using the 2 column sort approach in the first method.
Again, my gut feeling is that the first approach with 2 sort columns would be faster; and in my opinion easier to follow/maintain. The downfall is if the sort order defined changes then we have to change code. So... why have the order defined here... what isn't the order defined in a table; or is the order passed in as a parameter by user?

MAX(Date) is giving empty result

I have a table with exchange rate like below
And I am using the maxofdate to pick all these values based on currency code. But the query is giving blank.
Select USDAMOUNT * dbo.EXCHANGERATEAMT
from dbo.Amount_monthly
Left Join dbo.EXCHANGERATE on dbo.Amount_monthly.Currencycode=dbo.EXCHANGERATE.fromcurrencycode
WHERE ValidToDateTime = (Select MAX(ValidToDateTime) from dbo.EXCHANGERATE)
AND dbo.EXCHANGERATE.EXCHANGERATETYPECODE = 'DAY'
Using this statement
CONVERT(DATE,ValidToDateTime) = CONVERT(DATE,GETDATE()-1)
instead of subquery is giving me expected result.
Can someone correct this.
thanks in advance.
If I understand correctly, you need two things. First, the condition for the max() needs to match the condition in the outer query. Second, if you really want a left join, then conditions on the second table need to go in the on clause.
The resulting query looks like:
Select . . .
from dbo.Amount_monthly am Left Join
dbo.EXCHANGERATE er
on am.Currencycode = er.fromcurrencycode and
er.ValidToDateTime = (Select max(er2.ValidToDateTime)
from dbo.EXCHANGERATE er2
where er2.EXCHANGERATETYPECODE = 'DAY'
) and
er.EXCHANGERATETYPECODE = 'DAY';
I would write this using window functions, but that is a separate issue.
Try removing WHERE clause for ValidToDateTime and include it in the JOIN as AND condition
SELECT USDAMOUNT * dbo.EXCHANGERATEAMT
FROM dbo.Amount_monthly
LEFT JOIN dbo.EXCHANGERATE
ON dbo.Amount_monthly.Currencycode = dbo.EXCHANGERATE.fromcurrencycode
AND ValidToDateTime = (SELECT MAX(ValidToDateTime) --remove WHERE clause
FROM dbo.EXCHANGERATE)
AND dbo.EXCHANGERATE.EXCHANGERATETYPECODE = 'DAY';
I cleaned up your query a bit: as the other folks mentioned you needed to close the parentheses around the MAX(Date) sub-query, and if you reference a LEFT JOINed table in the WHERE clause, it behaves like an INNER JOIN, so I changed to in INNER. You also had "dbo" sprinkled in as a field prefix, but that (the namespace) only prefixes a database, not a field. I added the IS NOT NULL check just to avoid SQL giving the "null values were eliminated" SQL warning. I used the aliases "am" for the first table and "er" for the 2nd, which makes it more readable:
SELECT am.USDAMOUNT * er.EXCHANGERATEAMT
FROM dbo.Amount_monthly am
JOIN dbo.EXCHANGERATE er
ON am.Currencycode = er.fromcurrencycode
WHERE er.ValidToDateTime = (SELECT MAX(ValidToDateTime) FROM dbo.EXCHANGERATE WHERE ValidToDateTime IS NOT NULL)
AND er.EXCHANGERATETYPECODE = 'DAY'
If you're paranoid like I am, you might also want to make sure the exchange rate is not zero to avoid a divide-by-zero error.

Query table based on input parameter

I have an input parameter to a query I'm trying to write. Basically, if mostRecentSnapshot == true then I want to select only the most recent records from the process run (basically where max(creationDate)) and if mostRecentSnapshot == false then select creationDate and other columns normally.
To me, it makes sense to do this if statement in the from clause, but I don't think that's possible. Normally I would use a CTE, but I those don't exist in MySQL.
What is the best way to achieve this?
It would be something along the lines of this:
SELECT
CASE mostRecentSnapshot WHEN FALSE THEN
(
processauditheader.creationDate as processCreationDate,
processauditheader.processName,
processauditheader.processType,
processauditheader.processHost,
processauditheader.processDatabase,
processauditheader.tableAudited,
processauditheader.processInvokedByName,
processauditheader.processInvokedByType,
processauditheader.processInvokedByDatabase,
processauditheader.processIntervalValue,
processauditheader.processIntervalField,
processauditheader.auditScenarios,
processaudititerationdetail.creationDate as iterationDate,
processaudititerationdetail.connectionId,
processaudititerationdetail.processDate,
processaudititerationdetail.tableRowCount,
processaudititerationdetail.tableRowCountLastDay,
processaudititerationdetail.previousProcessAuditIterationDetailID,
processauditmetricdetail.creationDate,
processauditmetricdetail.processAuditIterationDetailID,
processauditmetricdetail.auditMetric,
processauditmetricdetail.auditTotal,
processauditmetricdetail.auditExample
)
WHEN TRUE THEN
(
((SELECT MAX(processaudititerationdetail.creationDate) as maxSnapshot,
processaudititerationdetail.id
from reporting_audit.processaudititerationdetail
group by processaudititerationdetail.creationDate) mostRecent
JOIN reporting_audit.processaudititerationdetail ON mostRecent.id = processaudititerationdetail.id)
)
END
FROM reporting_audit.processauditheader
JOIN processaudititerationdetail ON processaudititerationdetail.processAuditHeaderID = processauditheader.id
LEFT JOIN processauditmetricdetail ON processauditmetricdetail.processAuditIterationDetailID = processaudititerationdetail.id
A query can only return a fixed set of columns. Perhaps the following does what you want:
select paid.*
from reporting_audit.processaudititerationdetail paid
where (not v_mostRecentSnapshot) or
paid.creation_date = (select max(paid2.creationDate from reporting_audit.processaudititerationdetail paid2);
It will either select all records from the table or only the record(s) that have the most recent creationDate.

count(*) in mysql returning only one record

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 COUNT() causing empty array() return

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?