Can anyone help with the examples as below, thanks a lot
id color date
1 red 01/01
1 red 01/02
1 yellow 01/03
1 red 02/01
2 red 01/01
2 blue 01/02
2 blue 02/02
3 red 01/01
4 red 02/01
The ideal output should be:
id pattern
1 (red, yellow) to (red)
2 (red, blue) to (blue)
3 (red)
4 (red)
The result displays two things:
The unique pattern within one month
should aggregate the pattern together within time ranges
Ex, we can see that id_1 has a pattern changes on Jan from (red,yellow) but on Feb, it only has one pattern (red). Therefore the final output should be (red,yellow) to (red)
The query that I have now is
select drv.id, extract(month from date) as month,
trim(trailing',' from (XMLAGG(TRIM(color)',' order by date)(varchar(10000)))) as pattern from
(select id, color,
lag(color)over(partition by id, extract(month from date) order by date) as prev_color
from table
qualify prev_color <> color
) as drv
group by id, extract(month from date)
The query is incomplete, and it returns result like below,
but is it possible that we may return it by month?
Is there any way that we can mix using XMLAGG and partition by?
Can anyone give any ideas? Thanks a lot!
You need a GROUP BY id in the outer query. In the inner query you can filter out the 'no change' rows but also need to include the date column so you can reference it in the outer query. By default XMLAGG adds a space between items but as long as there are no spaces in the values you can easily translate that to whatever delimiter you prefer. (If there can be embedded spaces, then you can append a delimiter to each entry with the concatenation operator || and trim off the last one, etc.)
select drv.id,
oreplace(XMLAGG(TRIM(color) order by theDate)(varchar(10000)),' ','-') as pattern from
(select id, color, theDate,
lag(color)over(partition by id order by theDate) as prev_color
from theTable
qualify prev_color is null or prev_color <> color
) as drv
group by 1
order by 1
I used theDate and theTable in this example because DATE and TABLE are reserved words.
Related
Imagine I have two tables:
Table A
Names
Sales
Department
Dave
5
Shoes
mike
6
Apparel
Dan
7
Front End
Table B
Names
SALES
Department
Dave
5
Shoes
mike
12
Apparel
Dan
7
Front End
Gregg
23
Shoes
Kim
15
Front End
I want to create a query that joins the tables by names and separates sum of sales by table. I additionally want to filter my query to remove string matches or partial matches in this case by certain names.
What I want is the following result
Table C:
A Sales Sum
B Sales Sum
18
24
I know I can do this with a query like the following:
SELECT SUM(A.sales) AS 'A Sales Sum', SUM(B.sales) AS 'B sales Sum' FROM A
JOIN B
ON B.names = A.Names
WHERE Names NOT LIKE '%Gregg%' OR NOT LIKE '%Kim%'
The problem with this is the WHERE clause doesn't seem to apply, or applies to the wrong table. Since the Names column doesn't exactly match between the two, what I think is happening is when they are joined 'ON B.names = A.Names', the extras from B are being excluded? When I flip things around though I get the same result, which is no filter being applied. The wrong result I am getting is the following:
Table D:
A Sales Sum
B Sales Sum
18
62
Clearly I have a syntax issue here since I'm pretty new to SQL. What am I missing? Thanks!
You don't need a join or a union of the tables and you shouldn't do it.
Aggregate in each table separately and return the results with 2 subqueries:
SELECT
(SELECT SUM(Sales) FROM A WHERE Names NOT LIKE '%Gregg%' AND Names NOT LIKE '%Kim%') ASalesSum,
(SELECT SUM(Sales) FROM B WHERE Names NOT LIKE '%Gregg%' AND Names NOT LIKE '%Kim%') BSalesSum
I think you want a union approach here:
SELECT
SUM(CASE WHEN src = 'A' THEN sales ELSE 0 END) AS "A Sales Sum",
SUM(CASE WHEN src = 'B' THEN sales ELSE 0 END) AS "B Sales Sum"
FROM
(
SELECT sales, 'A' AS src FROM A WHERE Names NOT IN ('Gregg', 'Kim')
UNION ALL
SELECT sales, 'B' FROM B WHERE Names NOT IN ('Gregg', 'Kim')
) t;
Here is a demo showing that the above query is working.
So im wondering if its possible for SQLite to understand number ranges.
I want to be able to have a range such as "25-30" and lookup "27" to see if it falls within that range.
The issue is that the range will contain some text beforehand such as "Alice 25-30"
An example of what Id be looking to achieve can be seen in Table3 of this link:
https://dbfiddle.uk/?rdbms=sqlite_3.27&fiddle=483f62c5fbf13998659cd5f7ebbb3ce9
More than happy for solutions that can break the string at the first number, but still keep the number so
Alice | 25-30
Not
Alice | 5-30 (ive seen this suggested before :D)
To actually create Table 3 ill be using either INNER or LEFT OUTER JOIN not just Re-creating the table but was speedier to do this
Thanks in advance.
You can do it with a join of the 2 tables like this:
INSERT INTO Table3 (`ID`, `Age`,'Age Range')
SELECT t1.ID, t1.Age, t2.`Age Range`
FROM Table1 t1 INNER JOIN Table2 t2
ON t1.Age + 0 BETWEEN `Age Range` + 0
AND SUBSTR(`Age Range`, INSTR(`Age Range`, '-') + 1) + 0
SQLite performs implicit conversions of strings to numbers when they are used in expressions with numeric operations like +0, so what the query does is to compare Age to the 1st and the 2nd part of Age Range numerically.
Note that + 0 would not be needed in ON t1.Age + 0 BETWEEN if you had defined Age as REAL which makes more sense.
Change the INNER join to LEFT join if you want the row from Table1 inserted to Table3 even if there is no matching Age Range.
See the demo.
Results:
ID
Age
Age Range
1
30
25-30
2
40.5
31-45
I have an SQLite Database, two of the tables look like this:
ID Name
1 Test1
2 Test2
3 Test3
4 Test4
ID Color
1 Blue
1 White
1 Red
2 Green
2 Red
4 Black
In the first Tables, ID is unique, the second table lists colors an ID has, it can be from 0 to n colors.
Now I want to select all Names exactly once, that have one or more given color. Lets say, I want to have all names associated with blue, white and/or green. The resultset should have the IDs 1 and 2.
I am completly lost here, as I normally dont do any SQL. I am just familiar with very basic SQL. What I would do is Join the tables together, but I dont know how I do that, as ID is not unique in the second table. Also there would be the problem of IDs beeing duplicated in the resultset, if it has multiple colors that I want to select.
Thanks in advance for any help.
You don't need a join for this. Get the list of IDs from the color table in a subquery, and fetch the names from the test table with an in clause:
sqlite> select * from tests where id in
(select id from colors where name in ('Blue', 'White', 'Green'));
1|Test1
2|Test2
Duplicates don't matter in the subquery, but you could use distinct if you want that list without duplicates in other contexts.
How do I merge the contents of two columns into one in SQLite? I'm not looking to union 2 columns, I just want SQLite to automatically copy the entire contents of two columns and dump them (in any order) into a single column. For example, suppose I have the following table:
Table1:
Column1: Column2:
Red, Yellow
Green, Red
Blue, Gold
Purple, Green
Black, White
And this is the desired result:
Red
Green
Blue
Purple
Black
Yellow
Red
Gold
Green
White
What's the simplest SQLite query that'll get to the desired result?
I tried the following: Select Column1 || Column2 FROM Table1;
But I got the undesired result:
RedYellow
GreenRed
BlueGold
PurpleGreen
BlackWhite
I think that UNION ALL should give you the result:
Select Column1 AS Column_1_2 FROM Table1
UNION ALL
Select Column2 AS Column_1_2 FROM Table1;
I have a data structure where I have two tables Alpha and Beta and they are one to many. For the sake of an example let's say that table alpha has a column for "State" and table B has "Colors you like" and you can pick more than one. I would like to build a report that has columns like this:
STATE TOTAL RED GREEN BLUE
Alaska 5 1 3 1
Florida 2 2 2 0
New York 10 5 8 1
The column TOTAL would be a count of the records in Alpha and as you can see due to the one to many relationship the sum of the colors can exceed the count. I suppose it could be less as well if people didn't like colors.
How would you build a report like this. I'll be using SQL Server and Reporting Services in .NET so it could either be a complex query that I just dump into a data table report or a less complex query with some counting and totaling done by the report. I just don't really know the best way to tackle this.
Since you don't know which colors are going to be the columns you should use the Matrix Control
You'll need to set up the query
SELECT
a.State,
b.ColorName,
COUNT(b.ColorID) ColorCount
FROM
alpha a
LEFT JOIN beta b
ON a.id = b.a_id
GROUP BY
a.State,
b.ColorName
Just drag state for the rows, color for the columns and ColorCount for the data (Count(ColorID) will display in the data field))
Note: The LEFT JOIN and Count(ColorID) instead of Count(*) are required if you want a 0 value to appear correctly.
If you did know the colors you could use PIVOT or the sum case technique
SELECT state SUM(CASE WHEN Color = 'RED' THEN 1 ELSE 0 END) as Red, ...