sum of numbers for a given column in a sqlite database - android-sqlite

I am trying to get the sum of similar items in my rows in sqlite.
For example, all the values of x,all the values for y and all the values for z. I know how to use the WHERE clause in my query but the problem with it is that it requires i compare the values to another parameter. For example a query like this:
select sum(number_column) from your_table where number_column = 'some_number'
From the above, i dont have 'some_number' to compare to. So i need a way to add all the values for each similar rows, kind of like grouping them together.
So i would end up with something like:
x 25
y 24
z 16
Is this possible? Any suggestions are welcomed.
EDIT:
I tried this after Cristian's suggestion:
private void getSumOfGroupedTime() {
SQLiteDatabase db = this.getReadableDatabase();
Cursor c = db.rawQuery("SELECT " + KEY_CREATED_AT_AM_PM + ",sum(quantity) as sum FROM " + TABLE_SALES
+ " GROUP BY " + KEY_CREATED_AT_AM_PM, null);
c.moveToFirst();
double i = c.getDouble(0);
Log.d("sum_values_", String.valueOf(i));
c.close();
}
But it returns 1 for the three similar items i added in which each of these items have 1 as quantity. I expected 3. I'm i doing it wrong?

Assuming you have a table that has the following structure:
+----------------+--------+
| KEY_CREATED_AT | number |
+----------------+--------+
| a | 132 |
| e | 264 |
| f | 142 |
| x | 132 |
| y | 122 |
| z | 112 |
+----------------+--------+
In order to have the sum of these separate values you would use the clause group by
So the query would be like this:
SELECT KEY_CREATED_AT,sum(number) as sum FROM table_name
GROUP BY KEY_CREATED_AT
Example here: sqlfiddle
private void getSumOfGroupedTime() {
SQLiteDatabase db = this.getReadableDatabase();
Cursor c = db.rawQuery("SELECT " + KEY_CREATED_AT_AM_PM + ",sum(quantity) as sum FROM " + TABLE_SALES
+ " GROUP BY " + KEY_CREATED_AT_AM_PM, null);
try {
while (c.moveToNext()) {
Double sum = c.getDouble(1);
Log.d("Sum is: " + sum);
}
} finally {
c.close();
}
}

Related

How can I have an SQL CASE statement generate distinguishing output

I try to create a binary column based on the value of another column. When wijkcode is 34406 stadsdeel should be assigned the value Center, in all other cases Misc.
update event_locations
set stadsdeel = temp.stadsdeel
from (select wijkcode,
case wijkcode when 34406 then 'Center'
else 'Misc'
end as stadsdeel
from event_locations
) as temp;
select * from event_locations;
and part of its output:
34406;"Center"
34406;"Center"
34406;"Center"
34408;"Center"
34409;"Center"
34403;"Center"
34406;"Center"
31005;"Center"
While it should be:
34406;"Center"
34406;"Center"
34406;"Center"
34408;"Misc"
34409;"Misc"
34403;"Misc"
34406;"Center"
31005;"Misc"
All codes are 'Center'. Clearly I do something wrong. I have tried case when wijkcode = 34406 but that results in the same output. Does some body know what I am doing wrong?
Why not use the CASE expression as the value to be set:
update event_locations
set stadsdeel = case wijkcode
when 34406 then 'Center'
else 'Misc'
end
See the demo.
Results:
| wijkcode | stadsdeel |
| -------- | --------- |
| 34406 | Center |
| 34406 | Center |
| 34406 | Center |
| 34408 | Misc |
| 34409 | Misc |
| 34403 | Misc |
| 34406 | Center |
| 31005 | Misc |
What you are doing wrong is that your subquery is not correlated to the main query. The result is a Carthesian product: every target row is updated with every subquery row.
You could add a where temp.wijkcode = dst.wijkcode to the query to pick only one row per row from the subquery.
(or use the compact form as shown in #forpas' answer)
update event_locations dst
set stadsdeel = temp.stadsdeel
from (select wijkcode,
case wijkcode when 34406 then 'Center'
else 'Misc'
end as stadsdeel
from event_locations
) as temp
WHERE temp.wijkcode = dst.wijkcode -- <<-- connect temp to the main query
;
But you could also put the connection inside the subquery, it will now result in exactly one matching roe per row:
update event_locations dst
set stadsdeel = temp.stadsdeel
from (select
case wijkcode when 34406 then 'Center' else 'Misc' end as stadsdeel
from event_locations src
WHERE src.wijkcode = dst.wijkcode
) as temp;
Or, you can reduce the subquery to a scalar subquery, resulting in only one *value per row.:
update event_locations dst
set stadsdeel = (select
case wijkcode when 34406 then 'Center' else 'Misc' end as stadsdeel
from event_locations src
WHERE src.wijkcode = dst.wijkcode
)
;
or, you can combine the two queries into one: the table is basically updated from itself, anyway:
update event_locations
set stadsdeel = case wijkcode when 34406 then 'Center' else 'Misc' end
;

Hyphen as blend_char doesn't seem to work

MariaDB> select id,name from t where type='B' and name='Foo-Bar';
+----------------+---------+
| item_source_id | name |
+----------------+---------+
| 2000245 | Foo-Bar |
+----------------+---------+
1 row in set (0.00 sec)
index base_index { # Don't use this directly; it's for inheritance only.
blend_chars = +, &, U+23, U+22, U+27, -, /
blend_mode = trim_none, trim_head, trim_tail, trim_both
}
source b_source : base_source {
sql_query = select id,name from t where type='B'
sql_field_string = name
}
index b_index_lemma : base_index {
source = b_source
path = /path/b_index_lemma
morphology = lemmatize_en_all
}
SphinxQL> select * from b_index_lemma where match('Foo-Bar');
Empty set (0.00 sec)
Other Sphinx queries have results, so the problem isn't e.g. that the index is empty. Yet the hyphenated form does not, and I'd like it to. Am I misusing blend_chars-cum-blend_mode?

List in the Case-When Statement in Spark SQL

I'm trying to convert a dataframe from long to wide as suggested at How to pivot DataFrame?
However, the SQL seems to misinterpret the Countries list as a variable from the table. The below are the messages I saw from the console and the sample data and codes from the above link. Anyone knows how to resolve the issues?
Messages from the scala console:
scala> val myDF1 = sqlc2.sql(query)
org.apache.spark.sql.AnalysisException: cannot resolve 'US' given input columns >id, tag, value;
id tag value
1 US 50
1 UK 100
1 Can 125
2 US 75
2 UK 150
2 Can 175
and I want:
id US UK Can
1 50 100 125
2 75 150 175
I can create a list with the value I want to pivot and then create a string containing the sql query I need.
val countries = List("US", "UK", "Can")
val numCountries = countries.length - 1
var query = "select *, "
for (i <- 0 to numCountries-1) {
query += "case when tag = " + countries(i) + " then value else 0 end as " + countries(i) + ", "
}
query += "case when tag = " + countries.last + " then value else 0 end as " + countries.last + " from myTable"
myDataFrame.registerTempTable("myTable")
val myDF1 = sqlContext.sql(query)
Country codes are literals and should be enclosed in quotes otherwise SQL parser will treat these as the names of the columns:
val caseClause = countries.map(
x => s"""CASE WHEN tag = '$x' THEN value ELSE 0 END as $x"""
).mkString(", ")
val aggClause = countries.map(x => s"""SUM($x) AS $x""").mkString(", ")
val query = s"""
SELECT id, $aggClause
FROM (SELECT id, $caseClause FROM myTable) tmp
GROUP BY id"""
sqlContext.sql(query)
Question is why even bother with building SQL strings from scratch?
def genCase(x: String) = {
when($"tag" <=> lit(x), $"value").otherwise(0).alias(x)
}
def genAgg(f: Column => Column)(x: String) = f(col(x)).alias(x)
df
.select($"id" :: countries.map(genCase): _*)
.groupBy($"id")
.agg($"id".alias("dummy"), countries.map(genAgg(sum)): _*)
.drop("dummy")

Split a string and populate a table for all records in table in SQL Server 2008 R2

I have a table EmployeeMoves:
| EmployeeID | CityIDs
+------------------------------
| 24 | 23,21,22
| 25 | 25,12,14
| 29 | 1,2,5
| 31 | 7
| 55 | 11,34
| 60 | 7,9,21,23,30
I'm trying to figure out how to expand the comma-delimited values from the EmployeeMoves.CityIDs column to populate an EmployeeCities table, which should look like this:
| EmployeeID | CityID
+------------------------------
| 24 | 23
| 24 | 21
| 24 | 22
| 25 | 25
| 25 | 12
| 25 | 14
| ... and so on
I already have a function called SplitADelimitedList that splits a comma-delimited list of integers into a rowset. It takes the delimited list as a parameter. The SQL below will give me a table with split values under the column Value:
select value from dbo.SplitADelimitedList ('23,21,1,4');
| Value
+-----------
| 23
| 21
| 1
| 4
The question is: How do I populate EmployeeCities from EmployeeMoves with a single (even if complex) SQL statement using the comma-delimited list of CityIDs from each row in the EmployeeMoves table, but without any cursors or looping in T-SQL? I could have 100 records in the EmployeeMoves table for 100 different employees.
This is how I tried to solve this problem. It seems to work and is very quick in performance.
INSERT INTO EmployeeCities
SELECT
em.EmployeeID,
c.Value
FROM EmployeeMoves em
CROSS APPLY dbo.SplitADelimitedList(em.CityIDs) c;
UPDATE 1:
This update provides the definition of the user-defined function dbo.SplitADelimitedList. This function is used in above query to split a comma-delimited list to table of integer values.
CREATE FUNCTION dbo.fn_SplitADelimitedList1
(
#String NVARCHAR(MAX)
)
RETURNS #SplittedValues TABLE(
Value INT
)
AS
BEGIN
DECLARE #SplitLength INT
DECLARE #Delimiter VARCHAR(10)
SET #Delimiter = ',' --set this to the delimiter you are using
WHILE len(#String) > 0
BEGIN
SELECT #SplitLength = (CASE charindex(#Delimiter, #String)
WHEN 0 THEN
datalength(#String) / 2
ELSE
charindex(#Delimiter, #String) - 1
END)
INSERT INTO #SplittedValues
SELECT cast(substring(#String, 1, #SplitLength) AS INTEGER)
WHERE
ltrim(rtrim(isnull(substring(#String, 1, #SplitLength), ''))) <> '';
SELECT #String = (CASE ((datalength(#String) / 2) - #SplitLength)
WHEN 0 THEN
''
ELSE
right(#String, (datalength(#String) / 2) - #SplitLength - 1)
END)
END
RETURN
END
Preface
This is not the right way to do it. You shouldn't create comma-delimited lists in SQL Server. This violates first normal form, which should sound like an unbelievably vile expletive to you.
It is trivial for a client-side application to select rows of employees and related cities and display this as a comma-separated list. It shouldn't be done in the database. Please do everything you can to avoid this kind of construction in the future. If at all possible, you should refactor your database.
The Right Answer
To get the list of cities, properly expanded, from a table containing lists of cities, you can do this:
INSERT dbo.EmployeeCities
SELECT
M.EmployeeID,
C.CityID
FROM
EmployeeMoves M
CROSS APPLY dbo.SplitADelimitedList(M.CityIDs) C
;
The Wrong Answer
I wrote this answer due to a misunderstanding of what you wanted: I thought you were trying to query against properly-stored data to produce a list of comma-separated CityIDs. But I realize now you wanted the reverse: to query the list of cities using existing comma-separated values already stored in a column.
WITH EmployeeData AS (
SELECT
M.EmployeeID,
M.CityID
FROM
dbo.SplitADelimitedList ('23,21,1,4') C
INNER JOIN dbo.EmployeeMoves M
ON Convert(int, C.Value) = M.CityID
)
SELECT
E.EmployeeID,
CityIDs = Substring((
SELECT ',' + Convert(varchar(max), CityID)
FROM EmployeeData C
WHERE E.EmployeeID = C.EmployeeID
FOR XML PATH (''), TYPE
).value('.[1]', 'varchar(max)'), 2, 2147483647)
FROM
(SELECT DISTINCT EmployeeID FROM EmployeeData) E
;
Part of my difficulty in understanding is that your question is a bit disorganized. Next time, please clearly label your example data and show what you have, and what you're trying to work toward. Since you put the data for EmployeeCities last, it looked like it was what you were trying to achieve. It's not a good use of people's time when questions are not laid out well.

How do you exclude a column from showing up if there is no value?

Question about a query I'm trying to write in SQL Server Management Studio 2008. I am pulling 2 rows. The first row being the header information, the second row being the information for a certain Line Item. Keep in mind, the actual header information reads as "Column 0, 1, 2, 3, 4,.... etc."
The data looks something like this:
ROW 1: Model # | Item Description| XS | S | M | L | XL|
ROW 2: 3241 | Gray Sweatshirt| | 20 | 20 | 30 | |
Basically this shows that there are 20 smalls, 20 mediums, and 30 larges of this particular item. There are no XS's or XL's.
I want to create a subquery that puts this information in one row, but at the same time, disinclude the sizes with a blank quantity amount as shown under the XS and XL sizes.
I want it to look like this when all is said and done:
ROW 1: MODEL #| 3241 | ITEM DESCRIPTION | Gray Sweatshirt | S | 10 | M | 20 | L | 30 |
Notice there are no XS or XL's included. How do I do make it so those columns do not appear?
Since you are not posting your query, nor your table structure, I guess it is with columns Id, Description, Size. If so, you could do this and just replace with your table and column names:
DECLARE #columns varchar(8000)
SELECT #columns = COALESCE (#columns + ',[' + cast(Size as varchar) + ']', '[' + cast(Size as varchar) + ']' )
FROM YourTableName
WHERE COUNT(Size) > 0
DECLARE #query varchar(8000) = 'SELECT Id, Description, '
+ #columns +'
FROM
(SELECT Id, Description, Size
FROM YourTableName) AS Source
PIVOT
(
COUNT(Size)
FOR Size IN ('+ #columns +')
) AS Pvt'
EXEC(#query)
Anyhow, I also agree with #MichaelFredickson. I have implemented this pivot solution, yet it is absolutely better to let the presentation layer to take care of this after just pulling the raw data from SQL. If not, you would be processing the data twice, one on SQL to create the table and the other in the presentation when reading and displaying the values with your c#/vb/other code.