I have the following scenario:
A user can pick from any one of the following options during a search:
0
1-3
4-6
7-9
10-12
12+
say they picked 0, 4-6 and 12+
The SQL where statement would be:
Where (total_count = 0
OR (total_count >= 4 AND total_count <= 6)
OR total_count > 12)
Now to get these values I am iterating through a checkbox list collection so was trying:
query = query.Where(tc => tc.total_count >= 4 && tc.total_count <= 6);
But this was adding an AND between the statements, how could I add an or. I realise that I could potentially build a list with integers in and do a contains but I don't know how much the 12+ would potentially go up to.
Thanks
I don't see the problem with adding "OR". all the "WHERE" clause need is a predicate(something that return true or false". or maybe i missed the point.
regarding you SQL example the equivalent would be
query.Where(tc=> tc.total_count == 0 || (tc.total_count >= 4 && tc.total_count <= 6) || tc.total_count > 12)
Related
I tested so much things to get my Query the fastest as i can.
The table has over 2.9 Million Rows. And thats the Query
SELECT id, name, price, pricebefore, link, imagelink, updated, site, siteid
FROM items
WHERE (case when pricebefore3 is NULL then pricebefore else pricebefore3*1.5 end) >= pricebefore
AND price < pricebefore
AND isbn != -1
AND 1 = CASE
WHEN (100-price/pricebefore*100) > 90 THEN updated < NOW() - INTERVAL ".$timeago." MINUTE
ELSE (100-price/pricebefore*100) > ".mysqli_real_escape_string($link, $percentage)."
END
".preg_quote($merchant)."
AND name LIKE '%".mysqli_real_escape_string($link, $search)."%'
ORDER BY updated DESC
LIMIT ".mysqli_real_escape_string($link, $perPage)."
OFFSET ".mysqli_real_escape_string($link, $site);
Explain the variables:
$timeago can be 0 or like 30 to get only items older than 30 minute
$percentage can be like 70 to show only items with more than 70 percentage on price difference
$merchant is that AND link REGEXP '".$merchant."' and the $merchant can look like that
amazon.de/gp/product|idealo.de
to get only items with that in the link (so only items from amazon.de and idealo.de
$search can be a keyword that includes in the name
$perPage and $site is for pagination. so 20 items per page, site 1
I tried so much different things but doesnt find a good way.
There is also a way without $search line when $search is not set (so no one is searching specific item)
$merchant is also ony set when user has something in $merchant otherwise its that $merchant = '';
does anyone have an idea to make that faster?
the sql is running with mysqli_connect just simple php file
and one more thing...
if i have this in regex, it is faster than the second one. But why?!
AND link REGEXP 'amazon.de/gp/product|idealo.de'
AND link REGEXP 'idealo.de'
The second is 2 secs slower than the first?!
If idealo.de is the domain, then have a column for domain and test it with =, not LINK '%idealo.de%', nor REGEXP 'idealo.de'. And have
INDEX(domain, updated)
What am I doing:
I'm attempting to take two tables, one with 2016 data and one with 2015 data, and subtract the cells in each column to display only the differences greater than or equal to 10,000, rounded to the nearest 100th place, in a new table.
The Issue:
I am able to get the new table to pop up with the correct amounts displayed for the subtraction part only. I'm not able to add any additional criteria to filter the results to display the >= 10000 or the rounding to the 100th spot.
After research it looks like my JOIN needs a subquery to display what i would like, but I've been messing around with it for hours now and I can't seem to get it to display anything when I add a sub. Any assistance would be great. Here is what I have that works without the >= 10000 and rounding:
SELECT
`prioryeardata`.location,
`currentdata`.`2010` - `prioryeardata`.`2010` AS '2010_Difference',
`currentdata`.`2011` - `prioryeardata`.`2011` AS '2011_Difference',
`currentdata`.`2012` - `prioryeardata`.`2012` AS '2012_Difference',
`currentdata`.`2013` - `prioryeardata`.`2013` AS '2013_Difference',
`currentdata`.`2014` - `prioryeardata`.`2014` AS '2014_Difference',
`currentdata`.`2015` - `prioryeardata`.`2015` AS '2015_Difference'
FROM `prioryeardata`
JOIN `currentdata`
ON `prioryeardata`.location = `currentdata`.location;
Have a look at the below query it may help (using sql-server)
select location,Round([2010_Difference],3).[2010_Difference],Round([2011_Difference],3)[2011_Difference]
,Round([2012_Difference],3)[2012_Difference],Round([2013_Difference],3)[2013_Difference]
,Round([2014_Difference],3)[2014_Difference],Round([2015_Difference],3)[2015_Difference] from
( SELECT
prioryeardata.location,
currentdata.year2010 - prioryeardata.year2010 AS [2010_Difference],
currentdata.year2011 - prioryeardata.year2011 AS [2011_Difference],
currentdata.year2012 - prioryeardata.year2012 AS [2012_Difference],
currentdata.year2013 - prioryeardata.year2013 AS [2013_Difference],
currentdata.year2014 - prioryeardata.year2014 AS [2014_Difference],
currentdata.year2015 - prioryeardata.year2015 AS [2015_Difference]
FROM prioryeardata
JOIN currentdata
ON prioryeardata.location = currentdata.location
) t where t.[2015_Difference]>=10000 --or .......
Edit
select location,Round([2010_Difference],3).[2010_Difference],Round([2011_Difference],3)[2011_Difference]
,Round([2012_Difference],3)[2012_Difference],Round([2013_Difference],3)[2013_Difference]
,Round([2014_Difference],3)[2014_Difference],Round([2015_Difference],3)[2015_Difference]
from
(select t.location
,case when [2010_Difference]>10000 then [2010_Difference] Else 0 End as [2010_Difference]
,case when [2011_Difference]>10000 then [2011_Difference] Else 0 End as [2011_Difference]
,case when [2012_Difference]>10000 then [2012_Difference] Else 0 End as [2012_Difference]
,case when [2013_Difference]>10000 then [2013_Difference] Else 0 End as [2013_Difference]
,case when [2014_Difference]>10000 then [2014_Difference] Else 0 End as [2014_Difference]
,case when [2015_Difference]>10000 then [2015_Difference] Else 0 End as [2015_Difference]
from
( SELECT
prioryeardata.location,
currentdata.year2010 - prioryeardata.year2010 AS [2010_Difference],
currentdata.year2011 - prioryeardata.year2011 AS [2011_Difference],
currentdata.year2012 - prioryeardata.year2012 AS [2012_Difference],
currentdata.year2013 - prioryeardata.year2013 AS [2013_Difference],
currentdata.year2014 - prioryeardata.year2014 AS [2014_Difference],
currentdata.year2015 - prioryeardata.year2015 AS [2015_Difference]
FROM prioryeardata
JOIN currentdata
ON prioryeardata.location = currentdata.location
) t where t.[2010_Difference]>=10000 or t.[2011_Difference]>=10000 or t.[2012_Difference]>=10000
or t.[2013_Difference]>=10000 or t.[2014_Difference]>=10000 or t.[2015_Difference]>=10000
)tt
If you want cells to show blank instead of a value, use a pattern like this under your SELECT:
CASE WHEN `currentdata`.`2015` - `prioryeardata`.`2015` >= 10000 THEN
`currentdata`.`2015` - `prioryeardata`.`2015` ELSE NULL END AS '2015_Difference'
strictly speaking the else null is unnecessary, I just put it in for your learning benefit
If you want to only show rows where the difference is greater than ten k put this in on the end of your query:
WHERE
`currentdata`.`2015` - `prioryeardata`.`2015` >= 10000
If you want to only show rows where all years were over ten k, add similar filters for other years separated by AND. If you want to show rows where any year was over ten k, separate them with OR
To round values to the nearest 100 (i.e. 12345 becomes 12300) I believe you would use
ROUND(12345,-2)
I have two MySQL statements (see below), I would like to combine them together so if they both result in a 1 then the end result will be 1. I'm not sure how to construct this and was hoping for some help.
select count(*)
from monitor
where name='job_starttime' and value < ( UNIX_TIMESTAMP( ) -600)
select count(*)
from monitor
where name='job_active' and value = 0
So for example I would like when both statements are true to result in a value of 1, if 1 or none are true it results in a 0.
I am working on a grading database. My students write a paper and are given a score from 6 to 1 on 7 different fields. A score of 6 is the best with 1 being the worst. The student must get an 80% and no more than one score of a 4 in any one field to pass.
edit: I am going to try and clean this up:
Currently there is one table with the following Fields:
Student_Name
Paper_Analysis (This field can have a value of 1 to 6, 6 being the best)
Paper_Purpose (This field can have a value of 1 to 6, 6 being the best)
Paper_Voice (This field can have a value of 1 to 6, 6 being the best)
Paper_Concision (This field can have a value of 1 to 6, 6 being the best)
Paper_Accuracy (This field can have a value of 1 to 6, 6 being the best)
Paper_Content (This field can have a value of 1 to 6, 6 being the best)
Paper_Reasoning (This field can have a value of 1 to 6, 6 being the best)
Paper_Score (This is a calculated field adding the Paper_Purpose, Paper_Voice, Paper_Concision, Paper_Accuracy, Paper_Content, Paper_Reasoning)
Paper_Average (This field is a percent calculated as [Paper_Score]/42
Paper_Pass (For a student to pass they must have above 80% in the Paper Average field. They are also only allowed one 4 in any of the Paper_Purpose, Paper_Voice, Paper_Concision, Paper_Accuracy, Paper_Content, Paper_Reasoning fields.)
The Paper_Pass field is what I am having trouble with. I used IIf([Paper_Average]>0.8,"PASS","FAIL"), but this does not take in to account the only one 4 rule.
Thanks for the welcome. I am willing to use SQL or whatever works best. The only caveat is I am pretty new to SQL.
Assuming the rule for passing is the following:
To pass, the average score has to be 80% or above and only one score is allowed to be 4 or below.
Then you could use this formula:
IIf(Paper_Average >= 0.8 AND -((Paper_Analysis <= 4) + (Paper_Purpose <= 4) + (Paper_Voice <= 4) + (Paper_Concision <= 4) + (Paper_Accuracy <= 4) + (Paper_Content <= 4) + (Paper_Reasoning <= 4)) <= 1,'PASS','FAIL') AS Paper_Pass
Why does this work?
A boolean value (that is something that can be True or False) has a numeric representation with True being -1 and False being 0. At least in Microsoft Office (which Access is a part of). I use this by summing up the result of each of the seven Paper fields being 4 or less. This is an example for the first two Paper fields:
(Paper_Analysis <= 4) + (Paper_Purpose <= 4)
If Paper_Analysis is 4 or less, then the first summand is -1. If Paper_Purpose is 4 or less as well, then the second summand is also -1, so the result is -2. If Paper_Purpose was, say, a 5, then the second summand would be 0 and the result -1.
If you do this for all 7 Paper fields and negate the result, then the result could be anything between 0 and 7, measuring the number of scores of 4 or below. To pass, this value has to be <= 1.
I'm having trouble with this SQL:
$sql = mysql_query("SELECT $menucompare ,
(COUNT($menucompare ) * 100 / (SELECT COUNT( $menucompare )
FROM data WHERE $ww = $button )) AS percentday FROM data WHERE $ww >0 ");
$menucompare is table fields names what ever field is selected and contains data bellow
$button is the week number selected (lets say week '6')
$ww table field name with row who have the number of week '6'
For example, I have data in $menucompare like that:
123456bool
521478bool
122555heel
147788itoo
and I want to select those, who have same word in the last of the data and make percentage.
The output should be like that:
bool -- 50% (2 entries)
heel -- 25% (1 entry)
itoo -- 25% (1 entry)
Any clearness to my SQL will be very appreciated.
I didn't find anything like that around.
Well, keeping data in such format probably not the best way, if possible, split the field into 2 separate ones.
First, you need to extract the string part from the end of the field.
if the length of the string / numeric parts is fixed, then it's quite easy;
if not, you should use regular expressions which, unfortunately, are not there by default with MySQL. There's a solution, check this question: How to do a regular expression replace in MySQL?
I'll assume, that numeric part is fixed:
SELECT s.str, CAST(count(s.str) AS decimal) / t.cnt * 100 AS pct
FROM (SELECT substr(entry, 7) AS str FROM data) AS s
JOIN (SELECT count(*) AS cnt FROM data) AS t ON 1=1
GROUP BY s.str, t.cnt;
If you'll have regexp_replace function, then substr(entry, 7) should be replaced to regexp_replace(entry, '^[0-9]*', '') to achieve the required result.
Variant with substr can be tested here.
When sorting out problems like this, I would do it in two steps:
Sort out the SQL independently of the presentation language (PHP?).
Sort out the parameterization of the query and the presentation of the results after you know you've got the correct query.
Since this question is tagged 'SQL', I'm only going to address the first question.
The first step is to unclutter the query:
SELECT menucompare,
(COUNT(menucompare) * 100 / (SELECT COUNT(menucompare) FROM data WHERE ww = 6))
AS percentday
FROM data
WHERE ww > 0;
This removes the $ signs from most of the variable bits, and substitutes 6 for the button value. That makes it a bit easier to understand.
Your desired output seems to need the last four characters of the string held in menucompare for grouping and counting purposes.
The data to be aggregated would be selected by:
SELECT SUBSTR(MenuCompare, -4) AS Last4
FROM Data
WHERE ww = 6
The divisor in the percentage is the count of such rows, but the sub-stringing isn't necessary to count them, so we can write:
SELECT COUNT(*) FROM Data WHERE ww = 6
This is exactly what you have anyway.
The divdend in the percentage will be the group count of each substring.
SELECT Last4, COUNT(Last4) * 100.0 / (SELECT COUNT(*) FROM Data WHERE ww = 6)
FROM (SELECT SUBSTR(MenuCompare, -4) AS Last4
FROM Data
WHERE ww = 6
) AS Week6
GROUP BY Last4
ORDER BY Last4;
When you've demonstrated that this works, you can re-parameterize the query and deal with the presentation of the results.