Mysql single column result to multiple column result - mysql

I have a problem with a MySQL query, the problem is I have the following table:
id, rep, val dates
1 rep1 200 06/01/2014
2 rep2 300 06/01/2014
3 rep3 400 06/01/2014
4 rep4 500 06/01/2014
5 rep5 100 06/01/2014
6 rep1 200 02/06/2014
7 rep2 300 02/06/2014
8 rep3 900 02/06/2014
9 rep4 700 02/06/2014
10 rep5 600 02/06/2014
and I want a result like this:
rep 01/06/2014 02/06/2014
rep1 200 200
rep2 300 300
rep3 400 900
rep4 500 700
rep5 100 600
thank you very much!

You seem to want the most recent row for each rep. Here is an approach that often performs well:
select t.*
from table t
where not exists (select 1
from table t2
where t2.repid = t.repid and
t2.id > t.id
);
This transforms the problem to: "Get me the rows in table t where there is no other row with the same repid and a larger id." That is the same logic as getting the last one, just convoluted a bit to help the database know what to do.
For performance reasons, an index on t(repid, id) is helpful.

You seem to want the val for each of the dates.
Assuming the dates you are interested in are fixed then you can do that as follows. For output date column you check of the row matches the date for that column. If so you use the value of val , if not you just use 0. Then you sum all the resulting values, grouping by rep. I have assumed a fixed format of date.
SELECT rep, SUM(IF(dates='2014/06/01'), val, 0) AS '2014/06/01', SUM(IF(dates='2014/06/02'), val, 0) AS '2014/06/02'
FROM sometable
GROUP BY rep
Or if you just wanted the highest val for each day
SELECT rep, MAX(IF(dates='2014/06/01'), val, 0) AS '2014/06/01', MAX(IF(dates='2014/06/02'), val, 0) AS '2014/06/02'
FROM sometable
GROUP BY rep
If the number of dates is variable then not really a direct way to do it (as the number of resulting columns would vary). It would be easiest to do this manly in your calling script based on the following, giving you one row per rep / possible date with a sum of the values of val for that rep / date combination:-
SELECT rep, sub0.dates, SUM(IF(sometable.dates=sub0.dates), val, 0)
FROM sometable
CROSS JOIN
(
SELECT DISTINCT dates
FROM sometable
) sub0
GROUP BY rep, sub0.dates

Related

Calculate running day difference in MySQL

I'd like tot calculate the difference in days from the current row, compared to the previous row. What I have now:
Here is my column is day difference
**Day_Diff**
351
363
363
But what I actually want:
**Day_Diff**
351
12
12
What query would I need to accomplish this?
This should do the work (if what you want is minimum in first row and then difference to the minimum, with table being the name of your table and day_diff the name of the column you named Day_diff):
See sqlfiddle :
SELECT
CASE WHEN t1.day_diff = t2.min_day_diff
THEN t1.day_diff
ELSE t1.day_diff - t2.min_day_diff
END
FROM mytable t1
LEFT JOIN (SELECT MIN(day_diff) AS min_day_diff FROM mytable) t2
ON True;

Mysql recursive substracting and multiplying grouped values

Couldn't really explain my problem with words, but with an example I can show it clearly:
I have a table like this:
id num val flag
0 3 10 1
1 5 12 2
2 7 12 1
3 11 15 2
And I want to go through all the rows, and calculate the increase of the "num", and multiply that difference with the "val" value. And when I calculated all of these, I want to add these results together, but grouped based on the "flag" values.
This is the mathematical equation, that I want to run on the table:
Result_1 = (3-0)*10 + (7-3)*12
Result_2 = (5-0)*12 + (11-5)*15
78 = Result_1
150 = Result_2
Thank you.
Interesting question. Unfortunately MYSQL doesn't support recursive queries, so you'll need to be a little creative here. Something like this could work:
select flag,
sum(calc)
from (
select flag,
(num-if(#prevflag=flag,#prevnum,0))*val calc,
#prevnum:=num prevnum,
#prevflag:=flag prevflag
from yourtable
join (select #prevnum := 0, #prevflag := 0) t
order by flag
) t
group by flag
SQL Fiddle Demo

Unable to apply WHERE/AND on MySQL table with 2 columns on MAMP

I thought I had a very simple query to perform, but I can't seem to make it work.
I have this table with 2 columns:
version_id trim_id
1 15
1 25
1 28
1 30
1 35
2 12
2 25
2 33
2 48
3 11
3 25
3 30
3 32
I am trying to get any version-id's that have say a sub-set of trim_id's. Let's say all version_id's that have trim_id's 25 and 30. My obvious attempt was :
SELECT * FROM table WHERE trim_id=25 AND trim_id=30
I was expecting to have version_id 1 and 3 as a result, but instead I get nothing.
I am working with the latest version of MAMP, which has some odd behavior, like in this case it just tells me its 'LOADING' and never gives me an error message or something. But that's normally the case when there is no data to return.
This is InnoDB, if that helps.
Thanks for your input.
Your query does not work because you are using AND and the trim_id cannot have two different values at the same time, so you need to apply Relational Division to get the result.
You will need to use something similar to the following:
SELECT version_id
FROM yourtable
WHERE trim_id in (25, 30)
group by version_id
having count(distinct trim_id) = 2
See SQL Fiddle with Demo.
This will return the version_id values that have both 25 and 30. Then if you wanted to include additional columns in the final result, you can expand the query to:
select t1.version_id, t1.trim_id
from yourtable t1
where exists (SELECT t2.version_id
FROM yourtable t2
WHERE t2.trim_id in (25, 30)
and t1.version_id = t2.version_id
group by t2.version_id
having count(distinct t2.trim_id) = 2);
See SQL Fiddle with Demo
SELECT *
FROM table
WHERE trim_id IN(25,30)

MS Access Crosstab query - sum of columns reported by month

I am putting together a Crosstab and I want a report for multiple column values (all numbers) grouped by month. Here is the SQL I used. I understand that this won't bring back the desired results. every "timex" column has a different number in it. I want a query that will return the sum of the column grouped by month.
TRANSFORM Sum(tblTimeTracking.time1+ tblTimeTracking.time2+ tblTimeTracking.time3+ tblTimeTracking.time4+ tblTimeTracking.time5+ tblTimeTracking.time6+ tblTimeTracking.time7+ tblTimeTracking.time8+ tblTimeTracking.time9+ tblTimeTracking.time10+ tblTimeTracking.time11+ tblTimeTracking.time12+ tblTimeTracking.time13+ tblTimeTracking.time14+ tblTimeTracking.time15+ tblTimeTracking.time16+ tblTimeTracking.time17+ tblTimeTracking.time18+ tblTimeTracking.time19+ tblTimeTracking.time20+ tblTimeTracking.time21+ tblTimeTracking.time22 ) AS Total
SELECT tbl_vlookup.Manager AS Manager
FROM tbl_vlookup INNER JOIN tblTimeTracking ON tbl_vlookup.[Associate Name] = tblTimeTracking.Associate
GROUP BY tbl_vlookup.Manager
PIVOT Format([Day],"yyyy-mm");
Associate Day Time 1 Time 2 Time 3 Time 4 Time 5 Time 6 Time 7
John Smith 12/1/9999 1 0 0 5.5 1 0.25 0.25
Something like this:
TRANSFORM Sum(q.Time1) AS SumOfTime1
SELECT q.Associate, q.Day
FROM (SELECT t.Associate, t.Day, t.Time1,"Time1" As TimeType
FROM tbl t
UNION ALL
SELECT t.Associate, t.Day, t.Time2,"Time2" As TimeType
FROM tbl t
UNION ALL
SELECT t.Associate, t.Day, t.Time3,"Time3" As TimeType
FROM tbl t) AS q
GROUP BY q.Associate, q.Day
PIVOT q.TimeType;
As I mentioned, you need to flatten the table. It only seems to be different types of data :)

Break Numbers List Into Min and Max Ranges

Brain is not working today and my google skills are failing me.
I have a column of numbers ranging from 1 - 1000. I want to dump the min and max values for 100 (or whatever I chose) record ranges into a temp table. The plan is to use this temp table to process ranges of records (in this example 100 at a time) in a larger table.
Swear I have done this before with a CTE but then I had something to group on. Here I just want to break up a single list of numbers into ranges of X.
The output from the temp table should look like:
Min Max
0 99
100 199
200 299
300 399
etc.
Thanks!
You can use this trick from Stuart Ainsworth:
http://codegumbo.com/index.php/2009/01/25/building-ranges-using-a-dynamically-generated-numbers-table/
Numbers tables are awesome, but he uses a dynamically generated numbers table, which is even awesome...r.
If you know all numbers are present in the source table, you can use a recursive CTE to generate the number ranges:
; with numbers as
(
select 0 as a
, 99 as b
union all
select a+100
, b+100
from numbers
where a < 900
)
select *
from numbers
If the source table is sparsely populated, you can limit it to numbers that are actually present like:
... insert CTE from above here ...
select min(ot.NumberColumn)
, max(ot.NumberColumn)
from numbers
left join
OtherTable ot
on ot.NumberColumn between numbers.a and numbers.b
group by
numbers.a
enter code hereI have been having a play with a CTE after you posted this and came up with the following, I would be interested to hear if it works for you at all.
DECLARE #segment int = 100
;
WITH _CTE
(rowNum, value)
AS
(
SELECT ROW_NUMBER() OVER(ORDER BY col01) -1, col01
FROM dbo.testTable
)
SELECT rowNum/#segment AS Bucket, MIN(Value) AS MinVal, MAX(Value) AS MaxVal
FROM _CTE
group by rowNum/#segment
ORDER BY Bucket
;
col01 in this case is the column that you want the min/max range values from, as is TestTable.