QlikView Sort Expression MATCH with an IF expression inside - sorting

I am trying to create a custom sort expression using an IF statement.
I have the following IF Expression:
=IF(VOTA >= -15 AND VOTA <= 15, '0',
IF(VOTA >= -60 AND VOTA <= -16, '-1 to 0',
IF(VOTA >= -120 AND VOTA <= -61, '-2 to -1',
IF(VOTA >= -180 AND VOTA <= -121, '-3 to -2',
IF(VOTA >= -240 AND VOTA <= -181, '-4 to -3',
IF(VOTA >= -241, '-4+',
IF(VOTA >= 60 AND VOTA <= 16, '1 to 0',
IF(VOTA >= 120 AND VOTA <= 61, '2 to 1',
IF(VOTA >= 180 AND VOTA <= 121, '3 to 2',
IF(VOTA >= 240 AND VOTA <= 181, '4 to 3',
IF(VOTA >= 241, '4+'
)))))))))))
Which Groups the field VOTA.
Then in a Sort Expression i have done this:
=MATCH((IF(VOTA >= -15 AND VOTA <= 15, '0',
IF(VOTA >= -60 AND VOTA <= -16, '-1 to 0',
IF(VOTA >= -120 AND VOTA <= -61, '-2 to -1',
IF(VOTA >= -180 AND VOTA <= -121, '-3 to -2',
IF(VOTA >= -240 AND VOTA <= -181, '-4 to -3',
IF(VOTA >= -241, '-4+',
IF(VOTA >= 60 AND VOTA <= 16, '1 to 0',
IF(VOTA >= 120 AND VOTA <= 61, '2 to 1',
IF(VOTA >= 180 AND VOTA <= 121, '3 to 2',
IF(VOTA >= 240 AND VOTA <= 181, '4 to 3',
IF(VOTA >= 241, '4+'
)))))))))))), '-4+', '-4 to -3', '-3 to -2', '-2 to -1', '-1 to 0', '0', '1 to 0','2 to 1','3 to 2','4 to 3','4+')
But it is still not sorting as required.

I managed to get this to sort by adding Dual('xx to xx', n) and sorting numerically.
=IF(VOTA <= -241, Dual('-4+',-5),
IF(VOTA >= -240 AND VOTA <= -181, Dual('-3 to -4',-4),
IF(VOTA >= -180 AND VOTA <= -121, Dual('-2 to -3',-3),
IF(VOTA >= -120 AND VOTA <= -61, Dual('-1 to -2',-2),
IF(VOTA >= -60 AND VOTA <= -16, Dual('0 to -1',-1),
IF(VOTA >= -15 AND VOTA <= 15, Dual('0',0),
IF(VOTA <= 60 AND VOTA <= 16, Dual('0 to 1',1),
IF(VOTA <= 120 AND VOTA <= 61, Dual('1 to 2',2),
IF(VOTA <= 180 AND VOTA <= 121, Dual('2 to 3',3),
IF(VOTA <= 240 AND VOTA <= 181, Dual('3 to 4',4),
IF(VOTA >= 241, Dual('4+',5)
)))))))))))

Related

Evaluate rules in prolog

I want to convert the following decision rules to Prolog language
------Decision Rules---------
if (Right-Weight <= 2.5) and (Left-Weight > 2.5) and (Left-Distance > 1.5) then class: R (proba: 95.4%) | based on 87 samples
if (Right-Weight > 2.5) and (Right-Distance <= 2.5) and (Left-Weight > 1.5) then class: R (proba: 71.08%) | based on 83 samples
if (Right-Weight <= 2.5) and (Left-Weight <= 2.5) and (Left-Distance > 2.5) then class: R (proba: 63.41%) | based on 41 samples
if (Right-Weight > 2.5) and (Right-Distance > 2.5) and (Left-Weight > 2.5) then class: L (proba: 63.54%) | based on 96 samples
if (Right-Weight > 2.5) and (Right-Distance > 2.5) and (Left-Weight <= 2.5) then class: L (proba: 98.48%) | based on 66 samples
if (Right-Weight > 2.5) and (Right-Distance <= 2.5) and (Left-Weight <= 1.5) then class: L (proba: 77.78%) | based on 27 samples
if (Right-Weight <= 2.5) and (Left-Weight <= 2.5) and (Left-Distance <= 2.5) then class: L (proba: 65.22%) | based on 23 samples
if (Right-Weight <= 2.5) and (Left-Weight > 2.5) and (Left-Distance <= 1.5) then class: L (proba: 50.0%) | based on 14 samples
-----------------------------
Tried to come up with the following rules in prolog.
classR(Right-Weight, Left-Weight, Left-Distance) :-
(Right-Weight <= 2.5) , (Left-Weight > 2.5) , (Left-Distance > 1.5);
(Right-Weight > 2.5) , (Right-Distance <= 2.5) , (Left-Weight > 1.5);
(Right-Weight <= 2.5) , (Left-Weight <= 2.5) , (Left-Distance > 2.5)
classL(Right-Weight, Left-Weight, Left-Distance) :-
(Right-Weight > 2.5) , (Right-Distance > 2.5) , (Left-Weight > 2.5);
(Right-Weight > 2.5) , (Right-Distance > 2.5) , (Left-Weight <= 2.5);
(Right-Weight > 2.5) , (Right-Distance <= 2.5) , (Left-Weight <= 1.5);
(Right-Weight <= 2.5) , (Left-Weight <= 2.5) , (Left-Distance <= 2.5);
(Right-Weight <= 2.5) , (Left-Weight > 2.5) , (Left-Distance <= 1.5)
evaluate(RW, LW, LD, RD, OP) :-
((RW =< 2.5),(LW > 2.5),(LD > 1.5) -> OP = 'R';
(RW > 2.5) , (RD =< 2.5) , (LW > 1.5) -> OP = 'R';
(RW =< 2.5) , (LW =< 2.5) , (LD > 2.5) -> OP = 'R';
(RW > 2.5) , (RD > 2.5) , (LW > 2.5) -> OP = 'L';
(RW > 2.5) , (RD > 2.5) , (LW =< 2.5) -> OP = 'L';
(RW > 2.5) , (RD =< 2.5) , (LW =< 1.5) -> OP = 'L';
(RW =< 2.5) , (LW =< 2.5) , (LD =< 2.5) -> OP = 'L';
(RW =< 2.5) , (LW > 2.5) , (LD =< 1.5) -> OP = 'L').

SWITCH with clauses differing by a constant increment

Below is my SWITCH. I want to put it in a loop. I want to constantly increase my SWITCH by 2.5, because I have a lot of different values from 0 to 1000.
Order Amount =
SWITCH (
TRUE(),
Order[Amount Order] >= 0 && Order[Amount Order] < 5 , "< 5",
Order[Amount Order] >= 5.1 && Order[Amount Order] <= 7.5, "5 - 7.5",
Order[Amount Order] >= 7.51 && Order[Amount Order] <= 10, "7.51 - 10",
Order[Amount Order] >= 10.01 && Order[Amount Order] <= 12.5, "10.01 - 12.5",
Order[Amount Order] >= 12.51 && Order[Amount Order] <= 15, "12.51 - 15",Blank())
Maybe This can help you, just let me know if it does. Thanks.
This formula succeeded for me:
Order Amount =
VAR _ceil = CEILING('Order'[Amount Order] / 2.5, 1) * 2.5
VAR _big_result = CONVERT(_ceil-2.49, STRING) & " - " & CONVERT(_ceil, STRING)
RETURN SWITCH(TRUE(),
'Order'[Amount Order] >= 0 && 'Order'[Amount Order] < 5 , "< 5",
'Order'[Amount Order] >= 5 && 'Order'[Amount Order] <= 7.5, "5 - 7.5",
_big_result)

'Custom' CountryData Entries in Mathematica

I have the following dataset – which may not be formatted correctly for this task – which refers to values that I want to indicate on a map, using the map as a sort of graph:
Dat2Countries = {{"Argentina", 32.63969016}, {"Australia",
65.6986192}, {"Bolivia", 13.19444444}, {"Brazil",
27.55511788}, {"Canada", 66.49547068}, {"Chile",
27.14539357}, {"China", 17.94765891}, {"Czech Republic",
58.45414706}, {"Egypt", 18.07371757}, {"El Salvador",
23.94366197}, {"France", 63.86621123}, {"Germany",
58.68321579}, {"Ghana", 21.39232133}, {"Greece",
57.06734961}, {"Indonesia", 17.46457699}, {"Israel",
90.84112638}, {"Italy", 57.48221752}, {"Japan",
54.9704008}, {"Jordan", 22.93290207}, {"Kenya",
23.60066645}, {"Lebanon", 19.74186819}, {"Malaysia",
16.5620438}, {"Mexico", 31.72258783}, {"Nigeria",
24.38177507}, {"Pakistan" , 20.4777854}, {"Poland",
60.54096673}, {"Russia", 28.77358356}, {"Senegal",
21.91780822}, {"South Africa", 19.03936205}, {"South Korea",
53.20728589}, {"Spain", 58.12532901}, {"Tunisia",
24.67799831}, {"Turkey", 45.59516911}, {"Uganda",
19.08127926}, {"United Kingdom", 66.5450176}, {"Venezuela",
14.66666667}}
And I want to 'overlay' this index on a map using something like this (sorry, I know this is far from elegant):
Graphics[{If[MemberQ[Map[First, Dat2Countries, {1}], #],
If[Map[Last, Dat2Countries, {1}] < 20,
RGBColor[0.0352941, 0.254902, 0.352941],
If[Map[Last, Dat2Countries, {1}] < 40 &&
Map[Last, Dat2Countries, {1}] >= 20,
RGBColor[0.305882, 0.498039, 0.592157],
If[Map[Last, Dat2Countries, {1}] < 60 &&
Map[Last, Dat2Countries, {1}] >= 40,
RGBColor[0.0705882, 0.568627, 0.835294],
If[Map[Last, Dat2Countries, {1}] < 80 &&
Map[Last, Dat2Countries, {1}] >= 60,
RGBColor[0.372549, 0.776471, 0.952941],
If[Map[Last, Dat2Countries, {1}] < 100 &&
Map[Last, Dat2Countries, {1}] >= 80,
RGBColor[0.368627, 0.694118, 0.701961], LightBrown]]]]]],
CountryData[#, "SchematicPolygon"]} & /# CountryData[]]
But I am not so familiar with the CountryData package – is it possible to use the package to indicate values on a map that aren't built into the package?
Thanks,
arebearit
Using your data list Dat2Countries as given, the map can be drawn like so:-
colourfunction[country_String] := Module[{cases, value},
Catch[
cases = Cases[Dat2Countries, {country, _}];
If[cases == {}, Throw[LightGray]];
value = cases[[1, 2]];
Which[
value < 20, RGBColor[0.0352941, 0.254902, 0.352941],
value < 40, RGBColor[0.305882, 0.498039, 0.592157],
value < 60, RGBColor[0.0705882, 0.568627, 0.835294],
value < 80, RGBColor[0.372549, 0.776471, 0.952941],
value < 100, RGBColor[0.368627, 0.694118, 0.701961],
True, LightBrown]]]
Graphics[{colourfunction[CountryData[#, "Name"]],
CountryData[#, "SchematicPolygon"]} & /# CountryData[]]

getting hour in groups - oracle - whats is wrong

whats is wrong with this query.
I need to get all hours of the 24 hours period to count hits per hour.
I want to make a case when 0-24 but I can not do the first work
SELECT
(
CASE WHEN (
CAST(TO_CHAR(dg_user_acess.dt_user_acess, 'HH24') >= '00')
AND
CAST(TO_CHAR(dg_user_acess.dt_user_acess, 'HH24') < '01')
)
THEN ('00:00 as 01:00')
ELSE '0' END
) as hour,
count(*)
FROM dg_user_acess
GROUP by hour
i get the error
Erro de SQL: ORA-00905: palavra-chave não encontrada
00905. 00000 - "missing keyword"
the table data is like this
pk| dt_user_acess
01| 2014-10-21 08:30:12
02| 2014-10-21 08:40:27
03| 2014-10-21 08:56:18
04| 2014-10-21 09:15:19
05| 2014-10-21 10:42:48
...
and the result I would like something like this (not write the case when all schedulesin query to not pollute the code)
'00:00 as 01:00' 0
'01:00 as 02:00' 0
'02:00 as 03:00' 0
'03:00 as 04:00' 0
'04:00 as 05:00' 0
'05:00 as 06:00' 0
'06:00 as 07:00' 0
'07:00 as 08:00' 0
'08:00 as 09:00' 3
'09:00 as 10:00' 1
'10:00 as 11:00' 1
'11:00 as 12:00' 0
'12:00 as 13:00' 0
'13:00 as 14:00' 0
'14:00 as 15:00' 0
'15:00 as 16:00' 0
'16:00 as 17:00' 0
'17:00 as 18:00' 0
'18:00 as 19:00' 0
'19:00 as 20:00' 0
'20:00 as 21:00' 0
'21:00 as 22:00' 0
'22:00 as 23:00' 0
'23:00 as 23:59' 0
whats is wrong with this query [?]
You have many (more or less severe) issues with your query -- in no particular order:
The correct syntax for CAST is CAST(value AS type)
You use hour as a column name, but it is a reserved word
You compare strings where it is probably numbers that you should compare
You seems to expect a "dense" result set, but as you don't use a join, there is no chance for the result set to have more rows than the original table (probably less in fact, as you GROUP BY)
Given your needs, you probably missed the EXTRACT(HOUR FROM ...) function. In order to extract all the "hits" for an hour, you would write that:
SELECT
EXTRACT(HOUR FROM dg_user_acess.dt_user_acess) as "hour"
FROM dg_user_acess
As you need to COUNT them (and since you cannot use an alias in a GROUP BY clause) you might use a sub-query. Don't worry too much about that: Oracle is smart enough to optimize that kind of request:
SELECT "hour", count(*) "cnt"
FROM (
SELECT
EXTRACT(HOUR FROM dg_user_acess.dt_user_acess) as "hour"
FROM dg_user_acess
) V
GROUP BY "hour";
Finally, as you need a dense output (i.e.: with all hours in the range 0-23), my option would be to use a join on a generated table:
SELECT "hour", NVL("cnt",0) "cnt"
FROM (
SELECT LEVEL "hour" FROM DUAL
CONNECT BY LEVEL < 24
) CLOCK
LEFT JOIN (
SELECT "hour", count(*) "cnt"
FROM (
SELECT
EXTRACT(HOUR FROM dg_user_acess.dt_user_acess) as "hour"
FROM dg_user_acess
) V
GROUP BY "hour"
) G
USING ("hour")
ORDER BY "hour";
All of this leads to rather complexly nested queries. But this has the benefit of being easy to write incrementally as you just see it. Now that I showed the basic building blocks, perhaps we could do a better job. Maybe that:
SELECT CLOCK."hour", COUNT(dg_user_acess.dt_user_acess) "cnt"
FROM (
SELECT LEVEL "hour" FROM DUAL
CONNECT BY LEVEL < 24
) CLOCK
LEFT JOIN dg_user_acess
ON CLOCK."hour" = EXTRACT(HOUR FROM dg_user_acess.dt_user_acess)
GROUP BY CLOCK."hour"
ORDER BY CLOCK."hour";
Depending your schema and data, this might or might not perform better than the previous version. Feel free to take some time to experiment all these queries on http://sqlfiddle.com/#!4/678a5/17
i get some result changing the group by and the condition of the case (and remove the cast).
I do not know if it's the best way to do this, but it worked
SELECT
(
CASE WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '00:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '01:00' ) THEN ('00:00 as 01:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '01:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '02:00' ) THEN ('01:00 as 02:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '02:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '03:00' ) THEN ('02:00 as 03:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '03:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '04:00' ) THEN ('03:00 as 04:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '04:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '05:00' ) THEN ('04:00 as 05:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '05:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '06:00' ) THEN ('05:00 as 06:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '06:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '07:00' ) THEN ('06:00 as 07:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '07:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '08:00' ) THEN ('07:00 as 08:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '08:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '09:00' ) THEN ('08:00 as 09:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '09:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '10:00' ) THEN ('09:00 as 10:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '10:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '11:00' ) THEN ('10:00 as 11:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '11:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '12:00' ) THEN ('11:00 as 12:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '12:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '13:00' ) THEN ('12:00 as 13:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '13:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '14:00' ) THEN ('13:00 as 14:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '14:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '15:00' ) THEN ('14:00 as 15:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '15:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '16:00' ) THEN ('15:00 as 16:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '16:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '17:00' ) THEN ('16:00 as 17:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '17:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '18:00' ) THEN ('17:00 as 18:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '18:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '19:00' ) THEN ('18:00 as 19:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '19:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '20:00' ) THEN ('19:00 as 20:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '20:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '21:00' ) THEN ('20:00 as 21:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '21:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '22:00' ) THEN ('21:00 as 22:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '22:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '23:00' ) THEN ('22:00 as 23:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '23:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '23:59' ) THEN ('23:00 as 23:59')
ELSE '0' END
) as hora,
count(*) as total
FROM dg_usuario_acesso
JOIN dg_usuario_sessao
ON dg_usuario_sessao.cd_usuario_sessao = dg_usuario_acesso.cd_usuario_sessao
WHERE dg_usuario_acesso.dt_usuario_acesso >= to_date('2014-09-19 00:00', 'YYYY-MM-DD HH24:Mi')
AND dg_usuario_acesso.dt_usuario_acesso <= to_date('2014-09-20 15:07', 'YYYY-MM-DD HH24:Mi')
AND dg_usuario_sessao.cd_usuario NOT IN (0,1,138)
group by (CASE WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '00:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '01:00' ) THEN ('00:00 as 01:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '01:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '02:00' ) THEN ('01:00 as 02:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '02:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '03:00' ) THEN ('02:00 as 03:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '03:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '04:00' ) THEN ('03:00 as 04:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '04:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '05:00' ) THEN ('04:00 as 05:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '05:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '06:00' ) THEN ('05:00 as 06:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '06:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '07:00' ) THEN ('06:00 as 07:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '07:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '08:00' ) THEN ('07:00 as 08:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '08:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '09:00' ) THEN ('08:00 as 09:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '09:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '10:00' ) THEN ('09:00 as 10:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '10:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '11:00' ) THEN ('10:00 as 11:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '11:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '12:00' ) THEN ('11:00 as 12:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '12:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '13:00' ) THEN ('12:00 as 13:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '13:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '14:00' ) THEN ('13:00 as 14:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '14:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '15:00' ) THEN ('14:00 as 15:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '15:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '16:00' ) THEN ('15:00 as 16:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '16:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '17:00' ) THEN ('16:00 as 17:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '17:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '18:00' ) THEN ('17:00 as 18:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '18:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '19:00' ) THEN ('18:00 as 19:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '19:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '20:00' ) THEN ('19:00 as 20:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '20:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '21:00' ) THEN ('20:00 as 21:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '21:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '22:00' ) THEN ('21:00 as 22:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '22:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '23:00' ) THEN ('22:00 as 23:00')
WHEN (TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') >= '23:00' AND TO_CHAR(dg_usuario_acesso.DT_USUARIO_ACESSO, 'HH24:Mi') < '23:59' ) THEN ('23:00 as 23:59')
ELSE '0' END
)
order by 1
and I got the result I would like
hour Total hits
00:00 as 01:00 10
04:00 as 05:00 8
07:00 as 08:00 4
08:00 as 09:00 14
09:00 as 10:00 84
10:00 as 11:00 25
11:00 as 12:00 14
12:00 as 13:00 7
13:00 as 14:00 5
14:00 as 15:00 7
15:00 as 16:00 22
16:00 as 17:00 19
17:00 as 18:00 28
18:00 as 19:00 7
19:00 as 20:00 16
21:00 as 22:00 2
23:00 as 23:59 2

How to group combined AND with OR statements using the Sequel GEM in Ruby?

I am fairly good at PHP (OOP & flat). And for the past year or so I have been tasked with maintaining a Ruby codebase; a skill I am still learning. I am not too clear on how to properly structure a filtering chain using Sequel so AND as well OR statements can be properly contained.
This is the MySQL query structure I want to have:
SELECT * FROM `some_objects`
WHERE (
(
((`datebegin` >= 1950) AND (`datebegin` <= 1959)) OR ((`dateend` >= 1950) AND (`dateend` <= 1959))
)
OR
((`datebegin` <= 1950) AND (`dateend` >= 1959))
AND
(NOT `datebegin` = 0) AND (NOT `dateend` = 0)
)
;
And this is the Sequel code fragment I am using:
some_objects = where{((datebegin >= start_year) & (datebegin <= end_year)) | ((dateend >= start_year) & (dateend <= end_year))}.
or{(datebegin <= start_year) & (dateend >= end_year)}.
where(~:datebegin => 0, ~:dateend => 0)
And this is what I am actually getting:
SELECT * FROM `some_objects`
WHERE (
(
((`datebegin` >= 1950) AND (`datebegin` <= 1959)) OR ((`dateend` >= 1950) AND (`dateend` <= 1959))
OR
((`datebegin` <= 1950) AND (`dateend` >= 1959))
)
AND
(NOT `datebegin` = 0) AND (NOT `dateend` = 0)
)
;
I have also tried different variations on the same Sequel code such as this:
some_objects = where(:datebegin => start_year..end_year).
or(:dateend => start_year..end_year).
or{|o|(o.datebegin <= start_year) & (o.dateend >= end_year)}.
where(~:datebegin => 0, ~:dateend => 0)
And this:
some_objects = where(:datebegin => start_year..end_year).
or(:dateend => start_year..end_year).
or{(datebegin <= start_year) & (dateend >= end_year)}.
where(~:datebegin => 0, ~:dateend => 0)
But I still end up with the first SQL structure where this whole chunk is basically ((AND OR AND OR)):
(
((`datebegin` >= 1950) AND (`datebegin` <= 1959)) OR ((`dateend` >= 1950) AND (`dateend` <= 1959))
OR
((`datebegin` <= 1950) AND (`dateend` >= 1959))
)
When I want ((AND OR AND) OR):
(
((`datebegin` >= 1950) AND (`datebegin` <= 1959)) OR ((`dateend` >= 1950) AND (`dateend` <= 1959))
)
OR
((`datebegin` <= 1950) AND (`dateend` >= 1959))
The issue with your initial query is that you are depending on the OR/AND precedence rules instead of using explicit parentheses. Your initial query could be expressed as:
SELECT * FROM `some_objects`
WHERE (
((`datebegin` >= 1950) AND (`datebegin` <= 1959))
OR
((`dateend` >= 1950) AND (`dateend` <= 1959))
OR
((`datebegin` <= 1950) AND (`dateend` >= 1959) AND (NOT `datebegin` = 0) AND (NOT `dateend` = 0))
)
You could express this in Sequel as:
DB[:some_objects].where{((datebegin >= start_year) & (datebegin <= end_year)) | ((dateend >= start_year) & (dateend <= end_year))}.
or{((datebegin <= start_year) & (dateend >= end_year)) & Sequel.negate(:datebegin => 0)}
Which yields the following SQL:
SELECT * FROM `some_objects` WHERE (
((`datebegin` >= 1950) AND (`datebegin` <= 1959))
OR
((`dateend` >= 1950) AND (`dateend` <= 1959))
OR
((`datebegin` <= 1950) AND (`dateend` >= 1959) AND (`datebegin` != 0))
)
This should perform the same as the SQL you used, but it is a bit more readable (e.g. datebegin != 0 instead of NOT datebegin = 0). Note that you don't need the NOT dateend = 0 filter, because it is a subset of the dateend >= 1959 filter.
Remember with Sequel if you're really up against the wall, just spell out your conditions the hard way:
records = where(%Q[
(
(`datebegin` >= 1950 AND `datebegin` <= 1959)
OR (`dateend` >= 1950 AND `dateend` <= 1959)
)
OR (`datebegin` <= 1950 AND `dateend` >= 1959)
])
Those "zero" dates are kind of annoying from a query perspective, they'd be better off as NULL so they wouldn't need to be excluded here. Since NULL is never greater than, less than, or equal to anything, it's invisible to these queries. Zero, on the other hand, is a valid number and has to be excluded.
As an example of how this works with ranges:
records = where(datebegin: (1950..1959)).or(dateend: (1950..1959))
Those are expressed with the BETWEEN operator. From an indexing perspective that's usually at least a little faster than a bounded range using AND.

Resources