SQLite possibility to join matching Rows into one? - sqlite

I have a n:m relation of following tables:
Game
g_id
g_name
Player
p_id
p_name
GamePlayer
gp_id
gp_p_id
gp_g_id
And a Query like this:
SELECT g_name, p_name
FROM GamePlayer
INNER JOIN Game ON g_id = gp_g_id
INNER JOIN Player ON p_id = gp_p_id;
this will return a Row for each entry inside GamePlayer. If I have two Games with three players each, this query will return 6 Rows with the name of the Game and the Player (where there are obviously only two different Game names), which looks like this:
GameName1 John
GameName1 Dan
GameName1 Phil
GameName2 Dan
GameName2 Pete
GameName2 Kate
I like to have ( in this case ) two Rows which are looking like this:
GameName1 John Dan Phil
GameName2 Dan Pete Kate
is this somehow possible?
Note:
There may be more than three Players in a Game

Creating columns based on data would require some kind of pivot function, which SQLite does not have.
What you can do is to use group_concat to merge multiple values into one column value:
SELECT g_name,
group_concat(p_name)
FROM Game
JOIN GamePlayer ON g_id = gp_g_id
JOIN Player ON gp_p_id = p_id
GROUP BY g_name

Related

SQLite - Joining 2 tables excluding certain rows based on a partial string match

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.

Multiple inner join returning wrong data

I have this query
select * from task
inner JOIN ec_child AS child ON child.id = task.for
inner join ec_family_member as mother ON task.for = mother.id
WHERE task.group_id = 'NEWBORNCHW'
AND task.status = 'READY'
AND task.code IN ('mother_followup', 'new_born_follow_up')
whenever I remove one of inner join I get data for mother_followup and new_born_follow_up from task table but if both inner join is present in query then I get data for new_born_follow_up from task table only, why is that why data I don't get data for mother_followup and new_born_follow_up from task table.
Thanks in advance!
fiddle:
https://www.db-fiddle.com/f/qTEs3492Lgoo3VunB7bWem/0
Edit:
concept is
table_for_mother_and_child_ids.
id_for_mother_or_child
1
2
mother.
id | name
1 | XYZ
child.
id | name
2 | details
Desired Output:
id |mother.name|child.name
my question is can we do inner join on tables that are not related, like is it necessary that first inner join with table has to have a relation with 3rd table on which 2nd inner join is made, or inner joins/joins can be on independent tables?

INNER JOIN Number Range Lookup on VARCHAR

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

SQLite: Multiple Table Join

I have a simple one two many relationship.
There are three tables
Main:
ID TITLE
________
1 Peter
2 Lars
Orders:
SKU MAIN_ID
___________
RFX 1
HNI 2
RRP 2
Tools:
NAME MAIN_ID
____________
FORK 1
KNIFE 1
SPOON 2
So orders and tools hava a MAIN_ID which refers to the Main table.
So Peter has the order RFX and the tools FORK and SPOON
Lars has the orders HNI and RRP and the tool SPOON.
How can I do a single query to find out which orders and tools peter has and which ones lars has?
I tried it with an inner join but then there are duplicate entries.
You probably want to use group_concat() to get the values in one row. However, you need to pre-aggregate the data before the join:
select m.*, o.skus, t.tools
from main m join
(select main_id, group_concat(sku) as skus
from orders
group by main_id
) o
on o.main_id = m.id join
(select main_id, group_concat(name) as tools
from tools
group by main_id
) t
on t.main_id = m.id;

Pivot Table in AX

I came across a problem in AX 2009 and I have to admit I'm basically clueless.
I would like to build a view (based on an AOT query or not; but from what I understand you can do more using an AOT query than strictly with a view) using a table which looks like this:
id status date
1 IN 10/10/2011
1 OUT 11/10/2011
2 OUT 12/10/2011
3 IN 13/10/2011
4 IN 14/10/2011
4 OUT 15/10/2011
The view would ideally look like this:
id IN_Date OUT_Date
1 10/10/2011 11/10/2011
2 *NULL* 12/10/2011
3 13/10/2011 *NULL*
4 14/10/2011 15/10/2011
In strict SQL or even using Microsoft Access it's a trivial task to do but I can't find a way to do it in AX 2009 since there is no "AS" option in views' fields. I don't want to use display methods since I want the view to be accessed from outside of AX. Any hint would be greatly appreciated!
You would like to do a full outer join on the table (joined with itself).
This is not supported in X++ or as a query joinMode, but can be simulated using two intermediate views with outer join combined with a union.
View 1:
select id, date as dateIn from table as table1
outer join date as dateOut from table as table2
where table2.id == table1.id and
table1.status == Status::In and
table2.status == Status::Out
View 2:
select id, date as dateOut from table as table1
outer join date as dateIn from table as table2
where table2.id == table1.id and
table1.status == Status::Out and
table2.status == Status::In
View 3:
select id, dateIn, dateOut from view1
union
select id, dateIn, dateOut from view2
The above is more or less SQL, which can be turned into AX queries and views.
A way to do that is given in this answer.

Resources