I have a column (*Purchasetype*), userid in video table purchasetype is some how containg values 0,1, 2,3,4,.. etc. I want two sum these value order by userid.
For ex: sum ( purchasetype ) order by userid but I want like this
if purchasetype= 0 then its value is 0.99
if purchasetype =1 or 20 then its value is 3.99
if purchasetype = 3 or 13or 22 then its value is 9.99
so on. Below is complete list
0 ,17= 0.99
1,20=3.99
2=6.99
3,13,22=9.99
4,5,6,7,8,,10,11,12=0.00
14=19.99
15,23=39.99
16,24=59.99
18,21=01.99
19=02.99
else
19.99
i want to sum all the values of purchasetype with their replaced values (given above) order by userid
do we can put condition inside the sum() function of mysql; If its possible then please give me solution , may be this will solve my problem
You would use the aggregate function SUM() and CASE:
select
SUM(CASE purchaseType
WHEN 0 or 17 THEN 0.99
WHEN 1 or 20 THEN 3.99
WHEN 3 or 13 or 22 THEN 9.99
WHEN 4 or 5 or 6 or 7 or 8 or 9 or 10 or 11 or 12 THEN 0
WHEN 14 THEN 19.99
WHEN 15 or 23 THEN 39.99
WHEN 16 or 24 THEN 59.99
WHEN 18 or 21 THEN 1.99
WHEN 19 THEN 2.99
ELSE 19.99 END) as Total
from yourTable
see SQL Fiddle with Demo
I think the best way is to create table ptPrices:
create table ptPrices (Purchasetype int, Price float);
insert into ptPrices values (0,0.99);
insert into ptPrices values (1,3.99);
....
insert into ptPrices values (19,2.99);
And then use this query:
select sum(isnull(ptPrices.Price,19.99)) from Table
left join ptPrices
on Table.Purchasetype=ptPrices.Purchasetype;
Although this doesn't use SUM from MySQL query, the logic will get the job done
$query = mysqli_query($link, "SELECT * FROM video");
while($row = mysqli_fetch_assoc($query)){
//Then set conditionals
if($row['purchase_type)==0 || $row['purchase_type)==17){
$values[] = 0.99;
//Then your mysqli_query here
}
elseif($row['purchase_type)==1 || $row['purchase_type)==20){
$values[]= 3.99;
}
elseif//Blah blah for all values
}
//After exhausting all the rows, add the SUM
$sum = array_sum($values); //$sum will be equal to the addition of all the vlues of the //array $values
Related
I need to extract and migrate values from one table to another. the source table contains sumarized values for a specific effectivity date. If a value is changed, a new line is written if something is changed on the component values with the data valid starting at this effective date.
source_id
entity_id
effective_date
component_1
component_2
component_3
int(ai)
int
date
int
int
int
1
159
2020-01-01
100
0
90
2
159
2020-05-01
140
50
90
3
159
2020-08-01
0
30
90
5
159
2020-12-01
0
30
50
i need now migrate this data to a new table like this. the goal is that selecting data for a given month the result is the valid data for this month is given.
id
source_id
entity_id
startdate
enddate
component_type
value
int(ai)
int
int
date
date
int
int
each row represents a value for a component valid for a period of month.
I now run the insert update for each effective month by setting it as a parameter.
I insert value changes as new rows to the table an prevent duplicates by using a unique key (entity_id,effective_date,component_type)
SET #effective_date = '2020-01-01';
INSERT INTO component_final
select NULL,
source_id,
entity_id,
effective_date,
NULL,
1,
component_1
FROM component_source
WHERE effective_date = #effective_date
AND component_1>0;
after migrating the first row it should be that result
id
source_id
entity_id
startdate
enddate
component_type
value
1
1
159
2020-01-01
NULL
1
100
2
1
159
2020-01-01
NULL
3
90
SET #effective_date = '2020-05-01';
INSERT INTO component_final
select NULL,
source_id,
entity_id,
effective_date,
NULL,
1,
component_1
FROM component_source
WHERE effective_date = #effective_date
AND component_1>0;
after migrating the second row it should be that result
id
source_id
entity_id
startdate
enddate
component_type
value
1
1
159
2020-01-01
2020-04-30
1
100
2
1
159
2020-01-01
NULL
3
90
3
2
159
2020-05-01
NULL
1
140
4
2
159
2020-05-01
NULL
2
50
so if there is a value change in the future an end date has to be set.
I'm not able to do the second step, updating the data, if the component is changed in the future.
Maybe it is possible to have it as triggers after insert new row with same entity and component - but I was not able to make it work.
Some ideas? I want to handle this only inside of the MySQL.
You do not need the column enddate in the table component_final, because it's value depends on other values in the same table:
SELECT
id,
source_id,
entity_id,
startdate,
( SELECT DATE_ADD(MIN(cf2.startdate),INTERVAL -1 DAY)
FROM component_final cf2
WHERE cf2.startdate > cf1.startdate
AND cf2.source_id = cf1.source_id
AND cf2.entity_id = cf1.entity_id
) as enddate,
component_type,
value
FROM component_final cf1;
I understand that the core issue is how to find the source_ids where a component changes (0 means a removal, so we don't want these entries in the result) and how to assign the respective end dates at the same time. For the sake of illustration I simplify your example a bit:
There is only one component_type (I take into account that there might then be consecutive entries with unchanged value)
there is only one entity_id, so we can ignore it
It should be easy to extend this simpler version to your real-world problem.
To this is an example input:
source_id
effective_date
value
1
2020-01-01
100
2
2020-01-03
100
3
2020-01-05
80
4
2020-01-10
0
5
2020-01-12
30
I would expect the following output to be generated:
source_id
start_date
end_date
value
1
2020-01-01
2020-01-04
100
3
2020-01-05
2020-01-09
80
5
2020-01-12
NULL
30
You can achieve this with one query by joing each row with the previous one to check if the value has changed (find the start dates of periods) and the first row that is in the future and has a different value (find the start of the next period). If there is no previous row, it is considered a start as well. If there is no later update of the value, we have no end_date.
SELECT
main.source_id,
main.effective_date as start_date,
DATE_SUB(next_start.effective_date, INTERVAL 1 DAY) as end_date,
main.value
FROM source main
LEFT JOIN source prev ON prev.effective_date = (
SELECT MAX(effective_date)
FROM source
WHERE effective_date < main.effective_date
)
LEFT JOIN source next_start ON next_start.effective_date = (
SELECT MIN(effective_date)
FROM source
WHERE effective_date > main.effective_date AND value <> main.value
)
WHERE
ISNULL(prev.source_id) OR prev.value <> main.value
AND main.value <> 0
ORDER BY main.source_id
As I said: This will have to be adapted to your problem, e.g. by adding proper join conditions for the entity_id.
#Luuk pointed out that you don't need the end date because it can be derived from the data. This would be the case if you had entries for the start of "0 periods" as well, i.e. if there is no value set. If you don't have entries for these, you can't derive the end from the start of the respectively next period since there might be a gap in between.
I have a MySQL table which has some records as follows:
unix_timestamp value
1001 2
1003 3
1012 1
1025 5
1040 0
1101 3
1105 4
1130 0
...
I want to compute the average for every 10 epochs to see the following results:
unix_timestamp_range avg_value
1001-1010 2.5
1011-1020 1
1021-1030 5
1031-1040 0
1041-1050 -1
1051-1060 -1
1061-1070 -1
1071-1080 -1
1081-1090 -1
1091-1100 -1
1101-1110 3.5
1111-1120 -1
1121-1130 0
...
I saw some similar answers like enter link description here and enter link description here and enter link description here but these answers are not a solution for my specific question. How can I get the above results?
The easiest way to do this is to use a calendar table. Consider this approach:
SELECT
CONCAT(CAST(cal.ts AS CHAR(50)), '-', CAST(cal.ts + 9 AS CHAR(50))) AS unix_timestamp_range,
CASE WHEN COUNT(t.value) > 0 THEN AVG(t.value) ELSE -1 END AS avg_value
FROM
(
SELECT 1001 AS ts UNION ALL
SELECT 1011 UNION ALL
SELECT 1021 UNION ALL
...
) cal
LEFT JOIN yourTable t
ON t.unix_timestamp BETWEEN cal.ts AND cal.ts + 9
GROUP BY
cal.ts
ORDER BY
cal.ts;
In practice, if you have the need to do this sort of query often, instead of the inline subquery labelled as cal above, you might want to have a full dedicated table representing all timestamp ranges.
I have a table named Table1 that looks like this
ID VALUES
1 050
2 50
3 100
4 010
5 300
I need to update the targeted value through the ID. In this case I want to remove leading 0 where ID is 1. This is the end result below:
ID VALUES
1 50
2 50
3 100
4 010
5 300
Bear in mind that Id 4 is remained the same. As I have only specified Id 1 to remove that zero.
Reason I want to do this way, is because I wan't to learn how to remove the leading zero and at the same time how I can remove the leading zero for a specific ID.
You can use TRIM to update the values in your table:
UPDATE Table1
SET `values` = TRIM(LEADING '0' FROM `values`)
WHERE id = 1;
SELECT * FROM Table1
Output:
id values
1 50
2 50
3 100
4 010
5 300
Demo on dbfiddle
You can try below
update tablename set value=substr(value,2,length(value)-1)
where id=1
Please try this
SELECT `id`,
(CASE
WHEN (LEFT(`values`,1) = 0 AND `id` = 1) THEN SUBSTR(`values`,2)
ELSE
`values`
END
) `values`
FROM `data`
DEMO
I'm trying to normalize some data, and can't seem to come up with a solution. What I have is a table like this:
weight position1 position2 position3
1 10 20 30
2 25 35 45
3 17 05 22
and one like this:
location position
6 1
7 1
8 2
9 2
10 2
11 3
12 3
How do I normalize the above so that given a location and a weight, I can find the value for a given position?
I can use Perl, Python, Excel, MySQL or pretty much any tool on the block to do the actual reshuffling of the data; where I'm having a problem is in coming up with a reasonable schema.
The desired outcome here is something like
if location == 11 -> position is 3
therefore,
if weight == 2 -> the value is 45
The only thing to do is "unpivot" your first table to this:
weight position value
1 1 10
1 2 20
1 3 30
2 1 25
2 2 35
2 3 45
3 1 17
3 2 05
3 3 22
The first two columns should contain unique pairs of values. If you have other information that only depends on weight, you would need another table for that. Same for positions.
Converting to the new model
If you already have the tables, then you can create the first table (t1) with this statement:
create table t1_new
select weight, 1 as position, position1 as value
from t1
union all
select weight, 2 as position, position2 as value
from t1
union all
select weight, 3 as position, position3 as value
from t1
Then, after verification of the result, drop t1, and rename t1_new to t1.
Querying from the new model
To query from these tables the value for a given location and weight, you should use a join:
select value
from t1
inner join t2 on t2.weight = t1.weight
where t2.location = 11
and t1.position = 3
I have a select statement that returns a single column of results that are not "linear" (they are calculated using sum() and group by). I would like to add an additional column to this query that displays their respective count as they appear in the result list.
For example:
Original Result
Sums
----
450
320
117
583
Desired Result
Count | Sums
----- ----
1 | 450
2 | 320
3 | 117
4 | 583
Is this possible in MySQL without using a temporary table?
Or more simply, is it possible to just start counting from 1 to n in a select statement?
something like:
SELECT ITERATE(1-99)
Iterate
-------
1
2
3
.
.
.
99
Perhaps using a stored procedure that accomplishes this?
One option is:
SELECT
#`rownum` := #`rownum` + 1 `Count`,
`t`.`id`,
SUM(`t`.`qty`) `Sums`
FROM
(SELECT #`rownum` := 0) der, `table` `t`
GROUP BY
`t`.`id`;
SQL Fiddle demo