I'm new to mysql. I'm trying to write a query to calculate the total and difference for multiple rows, and then put them in specific columns.
Eg. I want to sum all Entity'A' of Type'1' then subtract from the result, the sum of Entity'A' of type'0'. While simultaneously populating a table to show where this difference is positive or negative.
Sample table:
Entity Type Value
A 1 200
B 1 500
C 0 350
B 0 150
C 1 100
A 1 50
A 1 350
Expected Output:
Entity Diff-Positive Diff-Negative
A 600
B 350
C 250
Note that Entity'A' for example may not have an entry for Type'0'
This is basically aggregation. You need a conditional to split the values into separate columns. One way uses greatest():
select entity,
greatest(sum(case when type = 1 then value else - value end), 0) as diff_positive,
greatest(sum(case when type = 0 then value else - value end), 0) as diff_positive
from t
group by entity;
Related
Hello I have two table in my database, customers and shops.
I want to get all customers and clarify that a customer is a debtor or not.
For this job I want to create a mysql query that get the customers and join the shop table.
I want to set condition for if shops.price_status column = 1 come and sum price value in shops table.
Otherwise the value of those row for price column in shop table equal to 0.
My shop table structure with some example data
id customer_id product_id price price_status
1 81 12 300 1
2 81 12 100 0
3 81 15 200 1
4 90 10 600 0
5 90 15 50 1
6 63 16 10 0
And my customer table (You should know some customers don't shop any product by I want to see them)
id name
63. Eva
64. Nva
81. Ali
82. Bill
90. Mosh
An I want to get this result
Eva. 0. // Because price status = 0
Nva. 0.
Ali. 500 // because have two row that prices status = 1
Bill. 0.
Mosh. 50. // Because have one row with price status = 1
this can do with [MySQL if][1]
SELECT
c.`name`,sum(if(s.price_status=1,s.price,0)) as price
FROM
customer AS c
LEFT JOIN
shops AS s
ON
c.id=s.customer_id
GROUP BY
c.id;
if you accept null value in price you can use
SELECT
c.`name`,sum(s.price_status*s.price) as price
FROM
customer AS c
LEFT JOIN
shops AS s
ON
c.id=s.customer_id
GROUP BY
c.id;
I have the query below, which is supposed to get all the "record" fields from a mysql table called users. The record field's values must be bigger than 0 for it to count. and the query only returns true if 3 or more records found (where record > 0)
The query below makes sense to me, but its returning the following PHP error : Operand should contain 2 column(s)
$query = "
SELECT * FROM users u
WHERE (
SELECT COUNT(record) AS record,
SUM(CASE WHEN record > 0 THEN 1 ELSE 0 END)
FROM users
) >= 3
";
Can SUM and COUNT not be used in the same query? I've used them simultaneously in the past with no problems.
Any help would be great thank
EDIT ---------------------
Table : users
--------------
id value
--------------
1 1
2 1
3 1
4 0
5 0
6 -1
7 -10
8 0
I'd like to only return a result if the value field in the table above is bigger than 0. But I also only want to return a result if the total number of values found in the table (where value > 0) are 3 or more.
You can just use the count function to count, a where to limit the data, and the having function to check that you have the number of records you want.
select count(*) as counted
from users
where record > 0
having counted > 3
Demo: http://sqlfiddle.com/#!9/29ed41e/1
With the above query your PHP will have the results as the first index, or counted depending on how you fetch. You don't need to loop the fetch because there will only be 1 row returned.
Roughly:
$row = $query->fetch();
return $row['counted'];
The number of rows will be 1 so you don't want to count the number of rows, you want the actual returned value.
Look at my table below. When I have a value and cat, I want to check the id. If I have cat a and value 3, then I will get id 1, but if I get cat a and value 1, then return false, because value 1 is not greater than 2. The problem is that the greater sign is inside the table. I cannot figure a way to do it on mysql query, help please. I can alter the table value structure if need.
table
id cat value
1 a greater than 2
2 b less than 2
3 c less than 2
4 d greater than 5
$val = 3;
SELECT id FROM my_table WHERE value=$val and cat = a
table
id cat lbound ubound
1 a 2 2147483647 (Assuming signed int)
2 b -2147483648 2
3 c -2147483648 2
4 d 5 2147483647
$cat = 'a';
$val = 3;
SELECT id
FROM my_table
WHERE cat = $cat
AND lbound <= $val -- If you use nulls instead of default extreme values,
AND ubound >= $val -- then these two bounds comparisons will be more complicated
ORDER BY lbound DESC LIMIT 1 -- if overlapping ranges are possible
Design-wise I would prefer nulls for default "no bound" values, but expressions using OR's like AND (lbound IS NULL OR lbound <= $val), or functions like IFNULL(lbound,-2147483648) <= $val tend to disqualify index use.
MySQL
I have table, where i store user_matches and it result:
n_match id_user id_score
1 55 1
1 66 0
This mean, 'user with id=55 win match with id=1 to user with id=66'.
So, we have 10, 100, 1000 matches, where user win or lose to opponents:
n_match id_user id_score
1 55 1 (win)
1 66 0
2 55 0 (lose)
2 77 1
3 55 1 (win)
3 77 0
4 55 1 (win)
4 77 0
5 55 1 (win)
5 77 0
Ok. As u can see, user win 3 matches without losing (win series)- and that's what i need from my query.
Question: How could i get from this table the longest series of won matches? Is it possible without looping on sql side or server side- just from query?
Thx.
Edit: One of solution i just now understand,- to get all matches as string like 001010101111010101011, then split it into array of strings with separator '0' -> [1, 1, 1, 1111, ...] and just take the longest string length.
But in this case i have to write server side code =\ That's not good, but mb the fastest.
The best way to do this is to calculate the cumulative number of losses for any match. For a sequence of wins, this value is constant. You can then use group by to get the length of the longest such sequence.
This version of the query is database-neutral. It uses subqueries to get the counts:
select user_id, max(NumWinsInRow)
from (select user_id, cumlosses, count(*)-1 as NumWinsInRow
from (select m.*,
(select sum(case when id_score = 0 then 1 else 0 end) from user_matches m2 where m2.id_user = m.id_user and m2.n_match <= m.n_match
) as CumLosses
from user_matches m
) t
group by cumlosses, user_id
) t
group by user_id
This query should run faster if you have an index on user_matches(id_user, n_math, id_score).
I have a table, which consists of 3 fields:
id
name
status
Every time I get the results, it should give me 5 names whose status = 1.
Suppose the db contains following:
id name status
1 A 1
2 B 1
3 C 0
4 D 1
5 E 0
6 F 0
7 H 1
8 I 1
9 J 1
10 K 1
11 L 1
12 M 0
1st time, fetch should return: A,B,D,H,I (5 records)
2nd time, fetch should return: J,K,L,A,B (5 records)
UPDATE: I don't want typical pagenation. Consider I have 12 available names from A1 to A12. The first fetch should return A1-A5, second fetch A6-A10 and third fetch A11, A12, A1, A2, A3. So when I reach the end, I need to get records starting from the first to fill the 5 slots.
i am doing it in php with mysql
This looks like some sort of job allocation script?
You need 2 things:
the highest ID returned last time the script was run (lastID)
a number larger than the maximum ID in the table (bigNum)
Then you can write your query as
SELECT
id, name
FROM
table
WHERE
status=1
ORDER BY
(bignum + id) MOD (bigNum + lastID + 1)
LIMIT 5
Shazaam!
Keep track of the ids of the records returned, and for the following queries do:
select top 5 *
from (
select top 5 *
from MyTable
where status = 1
and id not in (1,2,4,7,8)
order by name
union
select top 5 *
from MyTable
where status = 1
order by name
) a
$q = mysql_query("SELECT name FROM table WHERE status = 1 LIMIT 5);
while ($row = mysql_fetch_row($q))
{
.... //first 5
}
$q = mysql_query("SELECT name FROM table WHERE status = 1 LIMIT 5,5);
while ($row = mysql_fetch_row($q))
{
.... //second 5
}
this uses the offset functionality of mysql- think of it as pagination for your results.