i have table with:
id
mode
1
B
2
B
3
A
4
A
5
A
6
A
7
B
8
B
9
C
10
C
11
C
12
B
13
A
14
A
15
A
16
B
17
C
18
B
19
C
20
B
21
B
i would like to count following sequences:
"start": xA -> xB -> xC
"stop": xC -> xB ->xA
so that final result for this table would be:
START = 2 (ID: 3-11, 13-17)
STOP = 1 (ID: 9-15)
Point is that i need to count only right mode changes, no matter how many times mode is recorded.
Can anybody help? (tnx!)
ok, i got this solved with:
select
sum(case when prev= "A" and nxt="C" then 1 else 0 end) as start,
sum(case when prev= "C" and nxt="A" then 1 else 0 end) as stop
from (
select id, prev, mode, nxt
from (
select
id,
LAG(mode)OVER (
partition by 1
order by id
) prev,
mode,
LEAD(mode)OVER (
partition by 1
order by id
) nxt
from prva
order by id
) sub
where mode <> nxt and mode="B"
) data
Related
I have 3 tables that I have joined in the MySQL query below. All works well EXCEPT I would like the timeadj value with a 1 in column countingtime
to show from table 'data', not the first timeadj value the query finds.
I know this needs to be a query within a query but I am going around in circles and getting no where.
SELECT ttt_entries.tttid, ttt_teams.teamname, data.RacersInTeam,
ttt_entries.CoffeeClass, SEC_TO_TIME(data.timeadj),
COUNT(IF(data.division=5,1,NULL)) 'A+',
COUNT(IF(data.division=10,1,NULL)) A,
COUNT(IF(data.division=20,1,NULL)) B,
COUNT(IF(data.division=30,1,NULL)) C,
COUNT(IF(data.division=40,1,NULL)) D
FROM ttt_entries
INNER JOIN ttt_teams
ON ttt_entries.tttid = ttt_teams.tttid
INNER JOIN (SELECT * FROM data ORDER BY data.countingtime DESC) as data
ON ttt_entries.tttid = data.teamid
WHERE ttt_entries.eventDate = DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE()) >4, -5, 2) + DAYOFWEEK(CURDATE())) * -1 DAY) -- last Thursday
AND data.wtrlid = '22'
GROUP BY ttt_teams.tttid
ORDER BY data.timeadj ASC
For example.... In Team 1 (data.teamid=1) there are 8 time values in timeadj. In the adjacent column (countingtime) is a value either 1 or 0 but only ever 1x 1 per team.
Table ttt_entries
ID tttid CoffeeClass
1 23 Mocha
2 52 Espresso
3 6 Frappe
Table ttt_teams
tttid Name
6 Team A
23 Team 1
52 Team 2
Table 'data'
id wtrlid teamid timeadj countingtime division
1 22 23 3467.123 0 10
2 22 23 3467.125 0 20
3 22 23 3467.432 0 10
4 22 23 3469.000 1 10
5 22 23 3469.112 0 10
6 22 23 3468.987 0 5
My code brings back
tttid teamname RacersInTeam CoffeeClass Time A+ A B C D
23 Team 1 6 Mocha 3467.123 1 4 1 0 0
I need it to bring back the same data but a different time:
tttid teamname RacersInTeam CoffeeClass Time A+ A B C D
23 Team 1 6 Mocha 3469.000 1 4 1 0 0
You can try below way -
SELECT ttt_entries.tttid, ttt_teams.teamname, data.RacersInTeam,
ttt_entries.CoffeeClass, SEC_TO_TIME(max(case when countingtime=1 then data.timeadj end)),
COUNT(IF(data.division=5,1,NULL)) 'A+',
COUNT(IF(data.division=10,1,NULL)) A,
COUNT(IF(data.division=20,1,NULL)) B,
COUNT(IF(data.division=30,1,NULL)) C,
COUNT(IF(data.division=40,1,NULL)) D
FROM ttt_entries
INNER JOIN ttt_teams
ON ttt_entries.tttid = ttt_teams.tttid
INNER JOIN (SELECT * FROM data ORDER BY data.countingtime DESC) as data
ON ttt_entries.tttid = data.teamid
WHERE ttt_entries.eventDate = DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE()) >4, -5, 2) + DAYOFWEEK(CURDATE())) * -1 DAY) -- last Thursday
AND data.wtrlid = '22'
GROUP BY ttt_teams.tttid
ORDER BY data.timeadj ASC
SELECT status
, COUNT(*) total
, COUNT(s.group_id) totalByGrp
, s.group_id Groupe
FROM server s
, status st
WHERE s.id = st.server_id
AND st.created = (SELECT MAX(ss.created)
FROM status ss
WHERE ss.server_id = s.id)
GROUP
BY st.status
, s.group_id
this query return this table
status total totalByGrp Groupe
canc 3 3 10
canc 2 2 11
inst 1 1 10
inst 2 2 11
new 2 2 10
prod 1 1 10
prod 2 2 11
i want group by GROUP(Horizontal nit vertical like table above) return the table like :
status total Grp_10 Grp_11
canc 5 3 2
inst 3 1 2
new 2 2 0
prod 3 1 2
ret 4 2 2
toRet 2 2 0
There is no easy way to do this in Mysql query. you will have to use case statement and manually convert the rows in to columns. Still you will have to know all possible combinations
select sum(case when Groupe = 10 then Groupe else 0 end ) as Grp_10,
...
...
from ...
Otherwise you may export the results to a CSV and do the necessary pivoting in spreadsheet software like excel
I am trying to compare 2 rows and display the same ones.I did browse but was not able to find the right solution.
Table A
Count status Division
20 A 1
30 B 2
10 c 1
12 z 1
From the above table I want to display whose division is same.
Count status Division
20 A 1
10 c 1
12 z 1
Try this
Select * from TableA
Group By Division
Having Count(*) > 1
Select * from TableA
Group By Division
having Count(*) = 1
Here i used case statement , it worked for me
select CompanyCode ,'Commission Pec', Year
,sum(case when CommissionType='Commission Recevied' then JAN else 0 end)/sum(case when CommissionType='Net Payments from WM' and isnull(JAN,0)<>0 then JAN else 1 end)
from Commission_Consolidate
group by CompanyCode,Year
end
I have a table of data in MS Access 2007. There are 6 fields per record, thousands of records. I want to make a sort of pivot table like object. That is, if any two rows happens to be the same in the first 4 fields, then they will end up grouped together into one row. The column headers in this pivot table will be the values from the 5th field, and the value in the pivot table will be the 6th field, a dollar amount. Think of the 5th field as letters A, B, C, D, E, F, G. So, the table I start with might have a row with A in the 5th field and $3.48 in the 6th field. Another row may match in the first 4 fields, have B in the 5th field and $8.59 in the 6th field. Another may match in the first 4 fields, have E in the 5th field and $45.20 in the 6th field. I want all these rows to be turned into one row (in a new table) that starts with the first 4 fields where they match, then lists $3.48, $8.59, $0.00, $0.00, $45.20, $0.00, $0.00, corresponding to column headers A, B, C, D, E, F, G (since no records contained C, D, F, G, their corresponding values are $0.00), and then ends with one more field that totals up the money in that row.
Currently, I have some VBA code that does this, written by someone else a few years ago. It is extremely slow and I am hoping for a better way. I asked a previous question (but not very clearly so I was advised to create a new question), where I was asking if there was a better way to do this in VBA. My question asked about reading and writing large amounts of data all at once in Access through VBA, which I know is a good practice in Excel. That is, I was hoping to take my original table and just assign the entire thing to an array all at once (as in Excel, instead of cell by cell), then work with that array in VBA and create some new array and then write that entire array all at once to a new table (instead of record by record, field by field). From the answers in that question, it seems like that is not really a possibility in Access, but my best bet might be to use some sort of query. I tried the Query Wizard and found the Cross Tab query which is close to what I describe above. But, there appears to be a max of 3 fields used in the Row Heading, whereas here I have 4. And, instead of putting $0.00 when a value is not specified (like C, D, F, G in my example above), it just leaves a blank.
Update (in response to Remou's comment to give sample data): Here is some sample data.
ID a b c d e f
7 1 2 3 5 A 5
8 1 2 3 5 B 10
9 1 2 3 5 C 15
10 1 2 3 5 D 20
11 1 2 3 5 E 25
12 1 2 4 4 A 16
13 1 2 4 4 B 26
14 1 3 3 7 D 11
15 1 3 3 7 B 11
The result should be:
a b c d an bn cn dn en Total
1 2 3 5 5 10 15 20 25 75
1 2 4 4 16 26 0 0 0 42
1 3 3 7 0 11 0 11 0 22
But, when I copy and paste the SQL given by Remou, the only output I get is
a b c d an bn cn dn en
1 2 3 5 5 10 15 20 25
This is, I think, what you want, but it would be better to consider database design, because this is a spreadsheet-like solution.
SELECT t0.a,
t0.b,
t0.c,
t0.d,
Iif(Isnull([a1]), 0, [a1]) AS an,
Iif(Isnull([b1]), 0, [b1]) AS bn,
Iif(Isnull([c1]), 0, [c1]) AS cn,
Iif(Isnull([d1]), 0, [d1]) AS dn,
Iif(Isnull([e1]), 0, [e1]) AS en
FROM (((((SELECT DISTINCT t.a,
t.b,
t.c,
t.d
FROM table3 t) AS t0
LEFT JOIN (SELECT t.a,
t.b,
t.c,
t.d,
t.f AS a1
FROM table3 t
WHERE t.e = "A") AS a0
ON ( t0.d = a0.d )
AND ( t0.c = a0.c )
AND ( t0.b = a0.b )
AND ( t0.a = a0.a ))
LEFT JOIN (SELECT t.a,
t.b,
t.c,
t.d,
t.f AS b1
FROM table3 t
WHERE t.e = "B") AS b0
ON ( t0.d = b0.d )
AND ( t0.c = b0.c )
AND ( t0.b = b0.b )
AND ( t0.a = b0.a ))
LEFT JOIN (SELECT t.a,
t.b,
t.c,
t.d,
t.f AS c1
FROM table3 t
WHERE t.e = "C") AS c0
ON ( t0.d = c0.d )
AND ( t0.c = c0.c )
AND ( t0.b = c0.b )
AND ( t0.a = c0.a ))
LEFT JOIN (SELECT t.a,
t.b,
t.c,
t.d,
t.f AS d1
FROM table3 t
WHERE t.e = "D") AS d0
ON ( t0.d = d0.d )
AND ( t0.c = d0.c )
AND ( t0.b = d0.b )
AND ( t0.a = d0.a ))
LEFT JOIN (SELECT t.a,
t.b,
t.c,
t.d,
t.f AS e1
FROM table3 t
WHERE t.e = "E") AS e0
ON ( t0.d = e0.d )
AND ( t0.c = e0.c )
AND ( t0.b = e0.b )
AND ( t0.a = e0.a );
Table3
ID a b c d e f
1 1 2 3 4 a €10.00
2 1 2 3 4 b €10.00
3 1 2 3 4 c €10.00
4 1 2 3 4 d €10.00
5 1 2 3 4 e €10.00
6 1 2 3 5 a €10.00
7 1 2 3 5 b
8 1 2 3 5 c €10.00
9 1 2 3 5 d €10.00
10 1 2 3 5 e €10.00
Result
There are two rows, because there are only two different sets in the first four columns.
a b c d an bn cn dn en
1 2 3 4 €10.00 €10.00 €10.00 €10.00 €10.00
1 2 3 5 €10.00 €0.00 €10.00 €10.00 €10.00
The way the sql above is supposed to work, is that it selects each of the four definition columns and the currency column from the table where the sort column has a particular sort letter and labels the currency column with the sort letter, each of these sub queries are then assembled, however, you can take a sub query and look at the results. The last one is the part between the parentheses:
INNER JOIN (SELECT t.a,
t.b,
t.c,
t.d,
t.f AS e1
FROM table3 t
WHERE t.e = "E") AS e0
I am trying to do some calculations based on record from master table and wanted store manipulated result into a separate test table.
>Table:Master:
>C1 C2 C3 C4
>---------- -------- -- --
>2011-02-19 Test-A 31 3
>2011-02-19 Test-B 34 3
>2011-02-19 Test-C 17 1
>2011-02-15 Test-A* 48 =I 4
>2011-02-15 Test-B 64 6
>2011-02-15 Test-C 55 5
>2011-02-11 Test-A 64 =I2 6
>2011-02-11 Test-B 53 5
>2011-02-11 Test-C 17 1
>2011-02-10 Test-A 12 =I3 1 =J
>2011-02-10 Test-B 02 0
>2011-02-10 Test-C 54 5
Three kinds of test conducted in random fashions in a same day; but for this case date is not much important; only last three test records are used for the calculation.
I am trying to perform sequential calculations as below; using 3rd oldest element. for example, for test A, I(iteration) will be 48 (3rd oldest record = column c3) and therefore R2 & R3 will be calculated based on I2 & I3. And at last displaying average of, R,R2,R3 - J. ( C4 = latest record. )
Expected result:
>Table:Test-A
>SR Date I I2 I3 I4
>-- ---------- ----- ----------- ----------- -------------------
>1 2011/02/17 48 -52.96 -24.18 -10.71
>Formula:
>SR Date R R2 R3 R4
>-- ---------- ----- ----------- ----------- -------------------
>1 today() 48=C3 (I*0.23-I2) (I*0.23-I3) =avg(I,I1,I2,I3)-C4
I guess I need to use sub/nested query with join, but i couldn't able to figure out how to handle I; all result will be placed in individual test tables. Your input will be much appreciated. TIA
Setup test case:
CREATE TABLE `m1`
(c1 DATE
,c2 VARCHAR(6)
,c3 SMALLINT
,c4 TINYINT
) DEFAULT CHARSET=latin1;
INSERT INTO `m1` VALUES
('2011-02-19','Test-A',31,3)
,('2011-02-19','Test-B',34,3)
,('2011-02-19','Test-C',17,1)
,('2011-02-15','Test-A',48,4)
,('2011-02-15','Test-B',64,6)
,('2011-02-15','Test-C',55,5)
,('2011-02-11','Test-A',64,6)
,('2011-02-11','Test-B',53,5)
,('2011-02-11','Test-C',17,1)
,('2011-02-10','Test-A',12,1)
,('2011-02-10','Test-B',02,0)
,('2011-02-10','Test-C',54,5);
This query makes use of one local variable (#i). Provide the test_name ('Test-A') and the date ('2011-02-17') in the query, shown as literals here.
SELECT o.tn AS `Test`
, o.dt AS `Date`
, SUM(CASE WHEN o.n = 1 THEN o.c3*1.00 ELSE NULL END) AS R
, SUM(CASE WHEN o.n = 1 THEN o.c3*0.23 WHEN o.n = 2 THEN -1.00*o.c3 ELSE NULL END) AS R2
, SUM(CASE WHEN o.n = 1 THEN o.c3*0.23 WHEN o.n = 3 THEN -1.00*o.c3 ELSE NULL END) AS R3
, AVG(CASE WHEN o.n < 4 THEN c3*1.00 ELSE NULL END)-SUM(CASE WHEN n = 3 THEN c4*1.00 ELSE NULL END) AS R4
FROM (
SELECT #i := #i + 1 AS n
, s.tn
, s.dt
-- , m.c1
, m.c3
, m.c4
FROM (SELECT '2011-02-17' AS dt,_latin1'Test-A' AS tn, #i := 0) s
JOIN m1 m
ON m.c2 = s.tn AND m.c1 <= s.dt
ORDER BY m.c1 DESC
LIMIT 0,3
) o
GROUP BY o.tn, o.dt
HAVING SUM(1) >= 3
You can run just the inner query, uncomment the m.c1 from the select list, to check the rows returned (1st, 2nd and 3rd latest, prior to the supplied date.
This query returns a different value for R3 than shown in the question, but the result returned by the query appears to be the correct result for the given formula.
Also, the formula for R4 references 5 values: avg(I,I1,I2,I3)-J3. The formula used in the query is effectively =avg(I1,I2,I3)-J3
To get the result for all tests, as of a given date:
SELECT o.tn AS `Test`
, o.dt AS `Date`
, SUM(CASE WHEN o.n = 1 THEN o.c3 ELSE NULL END) AS R
, SUM(CASE WHEN o.n = 1 THEN o.c3*0.23 WHEN o.n = 2 THEN -1.00*o.c3 ELSE NULL END) AS R2
, SUM(CASE WHEN o.n = 1 THEN o.c3*0.23 WHEN o.n = 3 THEN -1.00*o.c3 ELSE NULL END) AS R3
, AVG(CASE WHEN o.n <= 3 THEN c3*1.00 ELSE NULL END)-SUM(CASE WHEN n = 3 THEN c4 ELSE NULL END) AS R4
FROM (
SELECT #i := CASE WHEN #prev_tn = m.c2 THEN #i + 1 ELSE 1 END AS n
, #prev_dt := s.dt AS dt
, #prev_tn := m.c2 AS tn
, m.c1
, m.c3
, m.c4
FROM (SELECT '2011-02-17' AS dt, #i := 0, #prev_tn := NULL) s
JOIN m1 m
ON m.c1 <= s.dt
ORDER BY s.dt, m.c2, m.c1 DESC
) o
GROUP BY o.tn, o.dt
HAVING SUM(1) >= 3
(The HAVING clause guarantees that the query returns results only if there are at least three rows for a given test, preceding the given date.) Here is the query output for two different dates, the 17th and the 20th:
Test Date R R2 R3 R4
------ ---------- -- ------ ------ -----
Test-A 2011-02-17 48 -52.96 -0.96 40.33
Test-B 2011-02-17 64 -38.28 12.72 39.67
Test-C 2011-02-17 55 -4.35 -41.35 37.00
Test Date R R2 R3 R4
------ ---------- -- ------ ------ -----
Test-A 2011-02-20 31 -40.87 -56.87 41.67
Test-B 2011-02-20 34 -56.18 -45.18 45.33
Test-C 2011-02-20 17 -51.09 -13.09 28.67
(The query would be somewhat more involved, to get results for more than one date.)
This may not be the best way to solve the problem, but I've successfully used this approach with MySQL.