Re: [sqlite] GROUP BY months and years using integer data
>So that in all cases, "value" contains the value of stats.quantity when >the selected month shows up in the iteration loop, and Zero >when any other month shows up, so Summing the values (or indeed doing any >other kind of aggregate function on it) will only affect >stats.quantity values for the specific months. This will only work for SUM aggregates where n (the count of values) does not affect the outcome. For other aggregates (such as the built-in AVG), you will get incorrect results using: AVG(x * (y = 1)) because you will be adding "extra zero values" into the aggregate that ought not be there. This applies to any aggregate function in which the number of observations is significant (average, standard deviation, variance, kurtosis, etc). For these kinds of aggregates you will have to ensure that NULL is passed into (and ignored by) the aggregate function when the condition is not met: AVG(CASE WHEN y = 1 THEN x ELSE NULL END) ___ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
Re: [sqlite] GROUP BY months and years using integer data
On 2013/12/22 20:53, James K. Lowden wrote: Similarly any attribute can be Boolean if it is found to be an attribute of an object. Giuseppe is not Boolean, but he is human and likely male, so that: (Giuseppe = Human) is true or 1, and (Giuseppe = Female) is false or 0. For RDBMS and indeed most programming languages, any Boolean evaluated result can directly be inferred as the arithmetic values 0 and 1 so that I could make some programmatic assumptive statements based Yes, it's a bit of a trick. Boolean logic operates on true and false values. Any two distinct symbols can be used. It so happens SQLite apparently uses 1 and 0, but e.g. -1 and 0 or 'T' and 'F' would serve as well. True, when a character interpretation is given, but when converted to a value, as in Integer Byte value, it is always 1 and 0 with every compiler in existence - however this may not necessarily be the case in SQL (I will have to look up the Standard to actually confirm this), but it _is_ the case with SQLite on any platform because the interpretation is subjective to the SQLite engine's interpretation of parsed SQL and not the storage medium or processor of the target platform, as opposed to register bit-quantities and the like, as far as I know. Good point to notice or remind people of, when asking questions here and may try to use similar methods on other SQL engines. stats.quantity * (stats.which_month = 1) is *logically* nonsensical: the product of a numerical quantity and a a logical one. What would, say, "7 times false" mean? "false false false false false false false"? Haha, that is really ( false ^ 7 ), which is not true! I wonder if ( true! ) = true... ( 7 * false ) is false - obviously... but ( 7 * True ) can still be false - if you try to argue with my ex wife. Cheers! Ryan ___ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
Re: [sqlite] GROUP BY months and years using integer data
On 2013/12/22 09:55, Giuseppe Costanzi wrote: I don't know if I have understood well but the statment SUM(stats.quantity * (stats.which_month = 1)) SUM(stats.quantity * (stats.which_month = 2)) should be interpreted SUM stats.quantity IF stats.which_month = 1 is TRUE SUM stats.quantity IF stats.which_month = 2 is TRUE Kind of yes, although for more clarity I'd propose it stated like this: For JAN: Results = SUM ( value ) WHERE ( value = (stats.quantity * _1_) WHEN month is JAN value = (stats.quantity * _0_) WHEN month is NOT JAN ) For FEB: Results = SUM ( value ) WHERE ( value = (stats.quantity * _1_) WHEN month is FEB value = (stats.quantity * _0_) WHEN month is NOT FEB ) etc. So that in all cases, "value" contains the value of stats.quantity when the selected month shows up in the iteration loop, and Zero when any other month shows up, so Summing the values (or indeed doing any other kind of aggregate function on it) will only affect stats.quantity values for the specific months. Apologies for the roundabout way of explaining - I never quite had to explain this specific kind of thing to anyone, it's usually a bit embedded - and I'm sure the same goes for most others on this forum! Cheers, Ryan ___ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
Re: [sqlite] GROUP BY months and years using integer data
On Sun, 22 Dec 2013 05:35:55 +0200 RSmithwrote: > Similarly any attribute can be Boolean if it is found to be an > attribute of an object. Giuseppe is not Boolean, but he is human and > likely male, so that: (Giuseppe = Human) is true or 1, and > (Giuseppe = Female) is false or 0. > > For RDBMS and indeed most programming languages, any Boolean > evaluated result can directly be inferred as the arithmetic values 0 > and 1 so that I could make some programmatic assumptive statements > based Yes, it's a bit of a trick. Boolean logic operates on true and false values. Any two distinct symbols can be used. It so happens SQLite apparently uses 1 and 0, but e.g. -1 and 0 or 'T' and 'F' would serve as well. > stats.quantity * (stats.which_month = 1) is *logically* nonsensical: the product of a numerical quantity and a a logical one. What would, say, "7 times false" mean? "false false false false false false false"? I'm not sure SQLite necessarily evaluates "x = y" as 0 or 1 for all compilers and all architectures. If it does, if SQLite is *defined* to use 1 and 0 to represent true and false, and the SQL author is indifferent to issues of portability (and, arguably, obscurity) then the "number * boolean" construction might be attractive. It is certainly more compact. --jkl ___ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
Re: [sqlite] GROUP BY months and years using integer data
On 22-12-2013 08:55, Giuseppe Costanzi wrote: I don't know if I have understood well but the statment SUM(stats.quantity * (stats.which_month = 1)) SUM(stats.quantity * (stats.which_month = 2)) should be interpreted SUM stats.quantity IF stats.which_month = 1 is TRUE The original '(stats.which_month = 1)' equals to 1 if the month is january and to 0 if the month is not january so, this: > SUM(stats.quantity * (stats.which_month = 1)) can be read as: SUM(CASE WHEN stats.which_month = 1 THEN stats.quantity ELSE 0 END) Am'I still in the darkness? ___ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
Re: [sqlite] GROUP BY months and years using integer data
I don't know if I have understood well but the statment SUM(stats.quantity * (stats.which_month = 1)) SUM(stats.quantity * (stats.which_month = 2)) should be interpreted SUM stats.quantity IF stats.which_month = 1 is TRUE SUM stats.quantity IF stats.which_month = 2 is TRUE Am'I still in the darkness? On Sun, Dec 22, 2013 at 4:35 AM, RSmithwrote: > Boolean Logic 101 - Feel free to skip if this is not your thread! > > - > > In addition to other replies - Boolean logic is interesting in that it has > no real arithmetic value and can have only true or false as a value. It > doesn't fit too well as a high-level storage value of a system even though > it permeates low-level storage in every way - it can't be null for > instance, but in an RDBMS it _can_ be Null and it _can_ be arithmetic by > taking on the values 0 and 1 for false and true respectively. This has the > added advantage that it can be used in arithmetic statements which is what > Igor used to save considerable amounts of typing in your query. > > Whether or not it is faster in execution than a case statement is probably > up to some testing, but I am willing to bet it is somewhat faster > considering the relative complexity of a CASE statement. > > Any statement containing a comparison operator ends up being a Boolean > statement because it can be found to either be so, or not be so. Month is > not Boolean, but (Month = January) is definitely Boolean, because the > comparison is either true or false depending on the value of "Month". > > Similarly any attribute can be Boolean if it is found to be an attribute > of an object. Giuseppe is not Boolean, but he is human and likely male, so > that: > (Giuseppe = Human) is true or 1, and > (Giuseppe = Female) is false or 0. > > For RDBMS and indeed most programming languages, any Boolean evaluated > result can directly be inferred as the arithmetic values 0 and 1 so that I > could make some programmatic assumptive statements based on it, such as: > > HumanX's fertility period recurs every (28 * (HumanX = Female)) days. This > will be 0 days for men (28 * false) = (28 * 0) = 0, and 28 for ladies as > (28 * true) = (28 * 1) = 28 in the same logic. > > Similarly your odds of balding is roughly 0.04 + (35/Age)*((HumanX = Male) > * 10) since men have a roughly 40% chance of balding by age 35 which is > about 10 times more likely than women and the odds increase with age[1]. > > > Hope this makes clear how Booleans are used mathematically in high-level > code. Have a great day! > Ryan > > > [1] - http://www.statisticbrain.com/hair-loss-statistics/ > > > > On 2013/12/21 22:24, Giuseppe Costanzi wrote: > >> ...but stats.which_month is not a boolean, it represent a month... >> >> >> > ___ > sqlite-users mailing list > sqlite-users@sqlite.org > http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users > ___ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
Re: [sqlite] GROUP BY months and years using integer data
Boolean Logic 101 - Feel free to skip if this is not your thread! - In addition to other replies - Boolean logic is interesting in that it has no real arithmetic value and can have only true or false as a value. It doesn't fit too well as a high-level storage value of a system even though it permeates low-level storage in every way - it can't be null for instance, but in an RDBMS it _can_ be Null and it _can_ be arithmetic by taking on the values 0 and 1 for false and true respectively. This has the added advantage that it can be used in arithmetic statements which is what Igor used to save considerable amounts of typing in your query. Whether or not it is faster in execution than a case statement is probably up to some testing, but I am willing to bet it is somewhat faster considering the relative complexity of a CASE statement. Any statement containing a comparison operator ends up being a Boolean statement because it can be found to either be so, or not be so. Month is not Boolean, but (Month = January) is definitely Boolean, because the comparison is either true or false depending on the value of "Month". Similarly any attribute can be Boolean if it is found to be an attribute of an object. Giuseppe is not Boolean, but he is human and likely male, so that: (Giuseppe = Human) is true or 1, and (Giuseppe = Female) is false or 0. For RDBMS and indeed most programming languages, any Boolean evaluated result can directly be inferred as the arithmetic values 0 and 1 so that I could make some programmatic assumptive statements based on it, such as: HumanX's fertility period recurs every (28 * (HumanX = Female)) days. This will be 0 days for men (28 * false) = (28 * 0) = 0, and 28 for ladies as (28 * true) = (28 * 1) = 28 in the same logic. Similarly your odds of balding is roughly 0.04 + (35/Age)*((HumanX = Male) * 10) since men have a roughly 40% chance of balding by age 35 which is about 10 times more likely than women and the odds increase with age[1]. Hope this makes clear how Booleans are used mathematically in high-level code. Have a great day! Ryan [1] - http://www.statisticbrain.com/hair-loss-statistics/ On 2013/12/21 22:24, Giuseppe Costanzi wrote: ...but stats.which_month is not a boolean, it represent a month... ___ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
Re: [sqlite] GROUP BY months and years using integer data
On 21 Dec 2013, at 8:24pm, Giuseppe Costanziwrote: > On Sat, Dec 21, 2013 at 9:11 PM, Simon Slavin wrote: > >> On 21 Dec 2013, at 7:45pm, Giuseppe Costanzi >> wrote: >> >>> I am not sure to have understood the Igor's solution >>> >>> ...SUM(stats.quantity * (stats.which_month = 1)) AS gen >>> >>> which is the meaning of the operator * in the statement? >> >> Multiply. >> >> It works because "stats.which_month = 1" is a boolean and therefore >> evaluates to either 0 or 1. ...but stats.which_month is not a boolean, it represent a month... However "(stats.which_month = 1)" is a boolean. Simon. ___ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
Re: [sqlite] GROUP BY months and years using integer data
...but stats.which_month is not a boolean, it represent a month... On Sat, Dec 21, 2013 at 9:11 PM, Simon Slavinwrote: > > On 21 Dec 2013, at 7:45pm, Giuseppe Costanzi > wrote: > > > I am not sure to have understood the Igor's solution > > > > ...SUM(stats.quantity * (stats.which_month = 1)) AS gen > > > > which is the meaning of the operator * in the statement? > > Multiply. > > It works because "stats.which_month = 1" is a boolean and therefore > evaluates to either 0 or 1. > > Simon. > ___ > sqlite-users mailing list > sqlite-users@sqlite.org > http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users > ___ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
Re: [sqlite] GROUP BY months and years using integer data
On 21 Dec 2013, at 7:45pm, Giuseppe Costanziwrote: > I am not sure to have understood the Igor's solution > > ...SUM(stats.quantity * (stats.which_month = 1)) AS gen > > which is the meaning of the operator * in the statement? Multiply. It works because "stats.which_month = 1" is a boolean and therefore evaluates to either 0 or 1. Simon. ___ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
Re: [sqlite] GROUP BY months and years using integer data
thanks to all for the solutions. I am not sure to have understood the Igor's solution ...SUM(stats.quantity * (stats.which_month = 1)) AS gen which is the meaning of the operator * in the statement? regards and still thanks beppe On Sat, Dec 21, 2013 at 8:21 PM, James K. Lowdenwrote: > On Sat, 21 Dec 2013 17:30:50 +0200 > RSmith wrote: > > > Just move the scope of the grouping and use Nulls in stead of 0's, > > like this: > > > > SELECT stats.which_year AS year, > > SUM(CASE WHEN stats.which_month = 1 THEN stats.quantity ELSE NULL > > END) AS gen, > > ELSE NULL is the default > > sqlite> create table T ( t int not null primary key ); > sqlite> insert into T values (1) ; > sqlite> insert into T values (2) ; > sqlite> .nullvalue NULL > sqlite> select t, case t when 1 then 'one' end as tee from T; > 1|one > 2|NULL > > But I would recommend ELSE 0, on the principle that NULL arithmetic is > dodgy at best. > > BTW, "which_month" means the same as "month"; you could tack > "which" in front of any name without changing the meaning. > > --jkl > ___ > sqlite-users mailing list > sqlite-users@sqlite.org > http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users > ___ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
Re: [sqlite] GROUP BY months and years using integer data
On Sat, 21 Dec 2013 17:30:50 +0200 RSmithwrote: > Just move the scope of the grouping and use Nulls in stead of 0's, > like this: > > SELECT stats.which_year AS year, > SUM(CASE WHEN stats.which_month = 1 THEN stats.quantity ELSE NULL > END) AS gen, ELSE NULL is the default sqlite> create table T ( t int not null primary key ); sqlite> insert into T values (1) ; sqlite> insert into T values (2) ; sqlite> .nullvalue NULL sqlite> select t, case t when 1 then 'one' end as tee from T; 1|one 2|NULL But I would recommend ELSE 0, on the principle that NULL arithmetic is dodgy at best. BTW, "which_month" means the same as "month"; you could tack "which" in front of any name without changing the meaning. --jkl ___ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
Re: [sqlite] GROUP BY months and years using integer data
On 12/21/2013 10:30 AM, RSmith wrote: Just move the scope of the grouping and use Nulls in stead of 0's, like this: SELECT stats.which_year AS year, SUM(CASE WHEN stats.which_month = 1 THEN stats.quantity ELSE NULL END) AS gen, SUM(CASE WHEN stats.which_month = 2 THEN stats.quantity ELSE NULL END) AS feb, Or a bit more compact: SELECT stats.which_year AS year, SUM(stats.quantity * (stats.which_month = 1)) AS gen, SUM(stats.quantity * (stats.which_month = 2)) AS feb, ... -- Igor Tandetnik ___ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
Re: [sqlite] GROUP BY months and years using integer data
You are basically trying to group values where the individual values are different but each in itself accumulated in stead of accumulated for the grouping. Just move the scope of the grouping and use Nulls in stead of 0's, like this: SELECT stats.which_year AS year, SUM(CASE WHEN stats.which_month = 1 THEN stats.quantity ELSE NULL END) AS gen, SUM(CASE WHEN stats.which_month = 2 THEN stats.quantity ELSE NULL END) AS feb, SUM(CASE WHEN stats.which_month = 3 THEN stats.quantity ELSE NULL END) AS mar, SUM(CASE WHEN stats.which_month = 4 THEN stats.quantity ELSE NULL END) AS apr, SUM(CASE WHEN stats.which_month = 5 THEN stats.quantity ELSE NULL END) AS mag, SUM(CASE WHEN stats.which_month = 6 THEN stats.quantity ELSE NULL END) AS giu, SUM(CASE WHEN stats.which_month = 7 THEN stats.quantity ELSE NULL END) AS lug, SUM(CASE WHEN stats.which_month = 8 THEN stats.quantity ELSE NULL END) AS ago, SUM(CASE WHEN stats.which_month = 9 THEN stats.quantity ELSE NULL END) AS sett, SUM(CASE WHEN stats.which_month = 10 THEN stats.quantity ELSE NULL END) AS ott, SUM(CASE WHEN stats.which_month = 11 THEN stats.quantity ELSE NULL END) AS nov, SUM(CASE WHEN stats.which_month = 12 THEN stats.quantity ELSE NULL END) AS dic, stats.test_id AS test_id FROM stats WHERE stats.test_id = 420 GROUP BY which_year Have a great day! Ryan On 2013/12/21 10:42, Giuseppe Costanzi wrote: HI all, I've a table such CREATE TABLE 'stats' ( 'stat_id' INTEGER PRIMARY KEY, 'test_id' INTEGER, 'quantity' INTEGER, 'which_month' INTEGER, 'which_year' INTEGER, ) and I need to extract data with somenthing like SELECT stats.which_year AS year, CASE WHEN stats.which_month = 1 THEN SUM(stats.quantity) ELSE 0 END AS gen, CASE WHEN stats.which_month = 2 THEN SUM(stats.quantity) ELSE 0 END AS feb, CASE WHEN stats.which_month = 3 THEN SUM(stats.quantity) ELSE 0 END AS mar, CASE WHEN stats.which_month = 4 THEN SUM(stats.quantity) ELSE 0 END AS apr, CASE WHEN stats.which_month = 5 THEN SUM(stats.quantity) ELSE 0 END AS mag, CASE WHEN stats.which_month = 6 THEN SUM(stats.quantity) ELSE 0 END AS giu, CASE WHEN stats.which_month = 7 THEN SUM(stats.quantity) ELSE 0 END AS lug, CASE WHEN stats.which_month = 8 THEN SUM(stats.quantity) ELSE 0 END AS ago, CASE WHEN stats.which_month = 9 THEN SUM(stats.quantity) ELSE 0 END AS sett, CASE WHEN stats.which_month = 10 THEN SUM(stats.quantity) ELSE 0 END AS ott, CASE WHEN stats.which_month = 11 THEN SUM(stats.quantity) ELSE 0 END AS nov, CASE WHEN stats.which_month = 12 THEN SUM(stats.quantity) ELSE 0 END AS dic, stats.test_id AS test_id FROM stats WHERE stats.test_id = 420 GROUP BY which_year that return this "2009" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "71769" "420" "2010" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "68972" "420" "2011" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "65075" "420" "2012" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "50605" "420" if I add which_month in th e GROUP BY clause I've "2009" "5994" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "420" "2009" "0" "6112" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "420" "2009" "0" "0" "7046" "0" "0" "0" "0" "0" "0" "0" "0" "0" "420" "2009" "0" "0" "0" "5947" "0" "0" "0" "0" "0" "0" "0" "0" "420" "2009" "0" "0" "0" "0" "6471" "0" "0" "0" "0" "0" "0" "0" "420" "2009" "0" "0" "0" "0" "0" "6027" "0" "0" "0" "0" "0" "0" "420" "2009" "0" "0" "0" "0" "0" "0" "5841" "0" "0" "0" "0" "0" "420" "2009" "0" "0" "0" "0" "0" "0" "0" "3352" "0" "0" "0" "0" "420" "2009" "0" "0" "0" "0" "0" "0" "0" "0" "6564" "0" "0" "0" "420" "2009" "0" "0" "0" "0" "0" "0" "0" "0" "0" "7075" "0" "0" "420" "2009" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "6283" "0" "420" "2009" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "5057" "420" "2010" "6112" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "420" "2010" "0" "6201" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "420" "2010" "0" "0" "6890" "0" "0" "0" "0" "0" "0" "0" "0" "0" "420" "2010" "0" "0" "0" "5907" "0" "0" "0" "0" "0" "0" "0" "0" "420" "2010" "0" "0" "0" "0" "6246" "0" "0" "0" "0" "0" "0" "0" "420" "2010" "0" "0" "0" "0" "0" "5667" "0" "0" "0" "0" "0" "0" "420" "2010" "0" "0" "0" "0" "0" "0" "5185" "0" "0" "0" "0" "0" "420" "2010" "0" "0" "0" "0" "0" "0" "0" "3269" "0" "0" "0" "0" "420" "2010" "0" "0" "0" "0" "0" "0" "0" "0" "5963" "0" "0" "0" "420" "2010" "0" "0" "0" "0" "0" "0" "0" "0" "0" "6520" "0" "0" "420" "2010" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "6162" "0" "420" "2010" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "4850" "420" "2011" "5888" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "420" "2011" "0" "6027" "0" "0" "0" "0" "0" "0" "0" "0" "0" "0" "420" "2011" "0" "0" "6756" "0" "0" "0" "0" "0" "0" "0" "0" "0" "420" "2011" "0" "0" "0" "5889" "0" "0" "0" "0" "0" "0" "0" "0" "420" "2011" "0" "0" "0" "0" "6276" "0" "0" "0" "0" "0" "0" "0" "420" "2011" "0" "0" "0" "0" "0" "5985" "0" "0" "0" "0" "0" "0" "420" "2011" "0" "0" "0" "0" "0" "0" "4968"