counting rows matching criteria in mysql join , union >= and <=? - php

Select * FROM table WHERE a<=9 AND a>=4 AND b<=20 AND b>=16 AND c<=30 AND c>=26
Now I want to end up selecting from query 1 the results in which at least two of the following criteria are met.
Select * FROM table WHERE a<=7 AND a>=5 AND B<=19 AND B>=17 AND C<=29 AND c>=27
Numbers could be anything, although on query 2 these are lower for the less than eqaul and higher for the bigger than equal.
I want to be able to set the number of minimum coincidences to be met at query 2 with a number.
For example 5 coincidences must be met at query 2 to end up making a selection in query 1.
This is about range and matches count, if there is an easier way to achieve this great.

i think this kind of query will do your job
Select
*,
(IF(a<=7 AND a>=5,1,0) + IF(B<=19 AND B>=17,1,0) + IF(C<=29 AND c>=27,1,0))
as totalmatch
FROM table
HAVING totalmatch >=2

Try to use native MySQL function BEETWEN:
SELECT * FROM t1 WHERE key_col BETWEEN '2' AND '3';

Think it is something like this you want for the second query:-
Select *, CASE WHEN a<=7 THEN 1 ELSE 0 END + CASE WHEN a>=5 THEN 1 ELSE 0 END + CASE WHEN B<=19 THEN 1 ELSE 0 END + CASE WHEN B>=17 THEN 1 ELSE 0 END + CASE WHEN C<=29 THEN 1 ELSE 0 END + CASE WHEN c>=27 THEN 1 ELSE 0 END AS MatchCount
FROM table
WHERE a<=7
OR a>=5
OR B<=19
OR B>=17
OR C<=29
OR c>=27
HAVING MatchCount >= 2
Probably using the first query as a subselect instead of table.
EDIT - reading your latest response I think I misunderstood your requirement. However you could possibly find the differences between each values, get the absolute value of each difference and add them together to see how close / far the differences are.

Related

function results dont match query results php

EDIT: the responses work well but not quite what i was after i dont think i explained it very well, i just want to return 1 result per function so count how many odd numbers are in the result and count how many even numbers are in the result?
sql fiddle for the data
http://sqlfiddle.com/#!9/dfbfa7/1
Im trying to count even and odd numbers by splitting the the results using 2 functions but my results dont match up to the results in the mysql table.
data
select number from table group by number
results
1,4,6,7,8,9,11,12
function to return odd number count
SELECT
COUNT(CASE WHEN (number% 2) > 0 THEN number ELSE NULL END) as odd
FROM test.table
WHERE date = CURDATE() and time > now() - interval 60 second group by number
LIMIT 1
and the function to return even number count
SELECT
COUNT(CASE WHEN (number% 2) = 0 THEN number ELSE NULL END) as even
FROM test.table
WHERE date = CURDATE() and time > now() - interval 60 second group by number
LIMIT 1
i was hoping the results would be
odd = 4
even = 4
but instead im getting
odd = 8
even = 0
where am i going wrong?
Maybe try something like thise.
For even numbers:
COUNT(SELECT * FROM `table` WHERE mod(number, 2)=0);
For odd numbers:
COUNT(SELECT * FROM `table` WHERE mod(number, 2)>0);
This will return the only number of odd and even numbers, then collect those numbers with php.
COUNT will add up all the lines it traverses
In your case you must use SUM:
SUM(CASE WHEN (number% 2) > 0 THEN 1 ELSE 0 END) as odd
SUM(CASE WHEN (number% 2) = 0 THEN 1 ELSE 0 END) as even
for simple operations the IF is much cleaner than the CASE:
SUM(IF(number % 2 > 0, 1, 0)) as odd
SUM(IF(number% 2 = 0, 1, 0)) as even
The reason your query is returning wrong result is probably because you are using limit 1 try removing it also if you have to use group by use group by number in before you do calculations for this query, i have altered the query here for example.
SELECT
count(CASE WHEN (a.number% 2) = 0 THEN a.number ELSE NULL END) as even,
count(CASE WHEN (a.number% 2) <> 0 THEN a.number ELSE NULL END) as odd
FROM (select number from test group by number) a;
http://sqlfiddle.com/#!9/dfbfa7/22
for the set up you have created im getting 5 even and 5 odd in results, may be you have to recheck the condition you have in where clause if your results are different with actual data.

how to retrieve all rows from a table starting from the n'th row

I want to retrieve all rows from a table starting from the n'th row.
For example, if the table has 20 rows and n=9, I want to retrieve all elements Where the first part of the retrieved elements are the elements from 9 to 20 and the second part are form 1 to 8.
[9,10,...,19,20,1,2,...,7,8].
At first,I thought that I can use 2 queries to do that using LIMIT and OFFSET .
//retrieve the 2nd group
SELECT * FROM Tname WHERE 1 LIMIT (Tsize-n+1) OFFSET (n)
//retrieve the 1st group
SELECT * FROM Tname WHERE 1 LIMIT (n-1)
Where I calculate Tsize-n+1, n and n-1 before, and after retrieving elements I combine the two arrays.
But I don't think that this is the optimal solution (I don't want to use more than one query. and calculating the number of elements in the table is consuming).
Is there a better way to do that?
I have a simple idea. Just select all rows, then read first n rows and finally read remaining rows to the end. Just that!
You can also try this :
(SELECT * FROM Tname WHERE id >= n)
UNION (SELECT * FROM Tname WHERE id < n)
You can use small trick to do this:
SELECT * FROM Tname ORDER BY id >= n DESC, id ASC
This way you have results in that order [9,10,...,19,20,1,2,...,7,8].
If that didn't work (you don't know what id must be used as boundary) you can rearrange results in PHP:
$n = 9;
$resultsArray = array_merge(
array_slice($resultsArray, $n),
array_slice($resultsArray, 0, $n)
);
just reverse order by any column and pass the offset and limit
$data = SELECT * FROM table;
in php
krsort($data);
$chunked_data = array_chunk($data,9);

SQL count values from same column

Hi I have mysql table named content where i have a column "status" which have 3 values, converted, negotiating and received. now i want to count how many have status received, negotiating, and converted for developing a chart.
here is what i used:
SELECT status,
SUM(CASE WHEN status = 'converted' = 1 THEN 1 ELSE 0 END) AS converted,
SUM(CASE WHEN status = 'negotiating' = 1 THEN 1 ELSE 0 END) AS negotiating,
SUM(CASE WHEN status = 'Received NA' = 1 THEN 1 ELSE 0 END) AS ReceivedNA
FROM content GROUP BY status;
It shows me the result but in a way that i can not use it.
to feed my chart i used this:
$data = array(
array('converted', $converted),
array('negotiating', $negotiating),
array('received', $received)
);
So i guess some thing like this table will solve my problem:
status result
--------------------------- --------
converted 1
negotiating 5
received 4
So can anyone suggest how can modify my sql to get the expected result?
thanks again
Use GROUP By. Try this -
SELECT status, count(status) result FROM content GROUP BY status
To get the distinct count use GROUP BY.
select status,count(1) as result from content GROUP BY status;
Instead of using sum, count is always a better and easier way
EDIT-to answer the comment
The parameter to the COUNT function is an expression that is to be evaluated for each row. The COUNT function returns the number of rows for which the expression evaluates to a non-null value. ( * is a special expression that is not evaluated, it simply returns the number of rows.)
There are two additional modifiers for the expression: ALL and DISTINCT. These determine whether duplicates are discarded. Since ALL is the default, your example is the same as count(ALL 1), which means that duplicates are retained.
Since the expression "1" evaluates to non-null for every row, and since you are not removing duplicates, COUNT(1) should always return the same number as COUNT(*).
Will this work for you?
SELECT status, count(status) FROM content GROUP BY status;

Display dynamic ranges from a database table and count the rows within each range

I have database table like this:
I want to display different 5-year age ranges and the counts of students that are in that range like below:
Here, the lowest age is 10 so we first calculate the range 10-15. There are 5 students within that range. For the second range, we need to find the age>15 which is 18. So, the second range is from 18-23, and so on. I would appreciate any help where the range is automatically calculated and count the data within that range.
You can use a condition inside of a SUM() statement to get a count where that condition holds. I would count the conditions where the age is BETWEEN() the necessary range. Try this:
SELECT
SUM(age BETWEEN 10 AND 15) AS '10-15',
SUM(age BETWEEN 18 AND 23) AS '18-23',
SUM(age BETWEEN 26 AND 31) AS '26-31',
SUM(age BETWEEN 34 AND 39) AS '34-39'
FROM myTable;
This will only return one row, but it will have everything you need. Here is an SQL Fiddle example.
EDIT I misunderstood your question to automatically calculate the various ranges. I will leave my previous answer here because it may be beneficial to future readers looking for hard coded ranges. To do this, you'll have to set up a variable. I made a sort of running total type approach to get the groups. I started by setting #a to 0 before the query. Then, I needed to get two values:
The minimum age from the table where age > #a
5 greater than that variable.
I did this by changing the value of #a as necessary:
#a := (SELECT MIN(age) FROM myTable WHERE age >= #a)
#a := #a + 5
Then, I included these in a CONCAT() block and casted these values as chars in order to get the groups that I needed. It may look complicated, so I hope I explained the concept:
SELECT CONCAT
(CAST(#a := (SELECT MIN(age) FROM myTable WHERE age > #a) AS CHAR),
' - ',
CAST((#a := #a + 5) AS CHAR)) AS ageRange
FROM myTable
WHERE #a <= (SELECT MAX(age) FROM myTable);
Doing this gave me four rows, each with the age ranges you expect. I had to add the where clause because otherwise I would get one result row for each row in the table, which would give us several null rows.
Last, I included a subquery to get the count of students whose age is within the necessary range. Note that the first part changes the values of #a, so instead of checking from #a to #a + 5, I check from #a-5 to #a. Here is the final query:
SET #a = 0;
SELECT CONCAT(CAST(#a := (SELECT MIN(age) FROM myTable WHERE age > #a) AS CHAR), ' - ', CAST((#a := #a + 5) AS CHAR)) AS ageRange,
(SELECT COUNT(*) FROM myTable WHERE age BETWEEN #a - 5 AND #a) AS numStudents
FROM myTable
WHERE #a <= (SELECT MAX(age) FROM myTable)
GROUP BY ageRange;
It worked beautifully in SQL Fiddle. Completely dynamic and returns the various groups of 5 without any prior knowledge of which groups to take.
SELECT
CASE
WHEN age>=10 AND age<=15 THEN '10-15'
WHEN age>=18 AND age<=23 THEN '18-23'
WHEN age>=26 AND age<=31 THEN '26-31'
WHEN age>=34 AND age<=39 THEN '34-39'
ELSE 'OTHER'
END
AS age_range,
COUNT(*) as number_of_students
FROM table
GROUP BY age_range

mysql - select a column based on a combination of values from another column

hi i need to get the plistid based on a given combination of avid. For example i submitted a combination of 1 and 4 avid, it should return a plistid of 1. Another example is when i submitted a combination of 2 and 5 avid it should return a plistid of 5. And if i submitted 1 and 3 it should return nothing since they are of the same attributeid.
How can i generate it in mysql
here is my table
NOTE: avid can be a combination of 1,2,3 or 4 numbers depending on the number of avid's submitted.
First, find all the matches of avid by plistid and then check that they have different attributeid. You can do this with aggregation, as a variation of a set-within-sets query:
select plistid
from t
group by plistid
having sum(avid = 1) > 0 and
sum(avid = 4) > 0 and
count(distinct case when avid in (1, 4) then attributeid end) = 2
The first two conditions in the having clause are saying what avids you want. They are counting the number of times that avid appears with one of the values, each returns true only when at least one value is found. The last is saying that you need distinct attribute ids on the rows.
Try:
select plistid
from t
where avid in (1,4)
group by plistid
having count(distinct avid) =2
What about this?
SELECT t1.plistid
FROM t t1
JOIN t t2
ON t1.attributeid != t2.attributteid
AND t1.plistid = t2.plistid
WHERE
t1.avid = 1
AND t2.avid = 4
try this one:-
select a.plistid
from your_table a, your_table b
where a.plistid = b.plistid
and a.avid = <first param>
and b.avid = <second param>
and a.attributeid <> b.attributeid;

Categories