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;
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.
Maybe I'm missing something here but I feel this isn't such an uncommon thing to do in SQL.
I have a DB table1 with a lot of values, and several other tables that each have a foreign key to the primary key of table1. I want for every row in table1 to generate a list of all the tables which reference it.
For example, I have a table called Books, which contains rows describing different books. I then have a table called SchoolLibrary which contains rows of all the books their library has and where they are stored. Not all the books in Books appear in school library. I then have a table called PublicLibrary, which similarly contains rows of all the books they have, as well as information about who checked them out.
I would then want to select all the values in Books and add a column with a list of which libraries reference that book, so it would say either {1, []} or {1, [PublicLibrary]} or {1, [SchoolLibary, PublicLibrary]} for book with id 1, etc...
Perhaps more useful would be not only which table references it, but also the id of the row in that table which references it. So the list would be something like {1, [PublicLibrary: 5]}, so the row with id 5 in PublicLibrary references the book with id 1.
How can I do this?
After discussing with someone I realized there's a simple solution to this question. Just do a LEFT JOIN of all the tables
SELECT Books._id, SchoolLibrary._id, PublicLibrary._id
FROM Books
LEFT JOIN SchoolLibrary ON Books._id = SchoolLibrary.bookId
LEFT JOIN PublicLibrary ON Books._id = PublicLibrary.bookId
This will return a table with all the values in Books, with a column for the other tables. If the other tables reference Books, the id of which entry references Books will be stored. If it doesn't, it'll be NULL
For example (where SchoolLibrary and PublicLibrary have _id, bookId as columns):
Books SchoolLibrary PublicLibrary
----- ------------- -------------
1 1 | 1 1 | 2
2 2 | 3 2 | 3
3
With the above script, it will return the following:
Book._id SchoolLibrary._id PublicLibrary._id
-------- ----------------- -----------------
1 1
2 1
3 2 2
I've seen the similar problem with mysql, but I barely could find any solution for the problem with sqllite.
My sample table,
-----------------------------
ID | Product Name | Price
-----------------------------
1 A 2
2 B 2
3 C 1
4 D 3
5 E 2
Here I need to get the rows until the total for the price column is equal or smaller than 5 in ascending order.
You could do a Running total using the Product ID and ORDER BY Product ID like the one below:
SELECT p1.ID, p1.ProductName, p1.Price,
(SELECT SUM(p2.Price) FROM Products p2 WHERE p1.ID >= p2.ID ORDER BY p2.ID ) as RunningTotal
FROM Products p1
WHERE RunningTotal <= 5
ORDER BY p1.ID
See Fiddle Demo
Or using the Price and ORDER BY Price like one below:
SELECT p1.ID, p1.ProductName, p1.Price,
(SELECT SUM(p2.Price) FROM Products p2 WHERE p1.Price >= p2.Price ORDER BY Price )
as RunningTotal
FROM Products p1
WHERE RunningTotal <= 5
ORDER BY p1.Price;
See 2nd Fiddle Demo
It's probably best to do it in code as SQLite does not support an easy way to do cumulative sums as far as I know. You can create an index on the Price column.
Then running a query like
SELECT * FROM <table> ORDER BY Price
Note that this will not eagerly fetch all rows from the database, but just provide you with the cursor. Keep fetching the next row from the cursor until you reach the desired sum.
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
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.