I have a complicated query that I just cant create. I'm thinking of doing it with JOIN's but don't know where to start. I'll just try to explain my problem as clearly as possible.
I am creating software that deals with compensations. Every compensation can have several links (like in a chain). Each link is basically a customer. So, I'll just tell you the table structures:
Customer
CustomerID | Name
Compensation
CompensationID | CustomerID | Date
Link
LinkID | CompensationID | CustomerID | Sequential
Now, the Sequential field increases with every link added. Let me demonstrate by filling the tables with some data:
CustomerID | Name
-----------+-----
0 | Foo
1 | Bar
2 | Baz
CompensationID | CustomerID | Date
---------------+------------+------
0 | 0 | 2-2-2010
1 | 1 | 2-3-2010
LinkID | CompensationID | CustomerID | Sequential
-------+----------------+------------+-----------
0 0 0 0
1 0 2 1
2 0 1 2
So no matter what the LinkID/CompensationID/CustomerID the Sequential always goes from 0 to N in the Links table (depending on how many links a compensation has).
Now here is the problem: I want to list all Compensation's whose Link's meet the following requirements:
Search in Links
CustomerID = A
Sequential = 0 (first link) AND Sequential = LAST (in this case 2)
List compensations
Here is what I got so far:
SELECT * FROM Compensation JOIN Link ON Compensation.ID = Link.CompensationID
WHERE Link.CustomerID=A AND Link.Sequential = 0 AND Link.Sequential=LAST
This is more or less pseudo SQL since I know Link.Sequential cant be 0 and another value at the same time, but I don't know how to do this.
Any help would be appreciated.
Thank you.
P.S.
Sorry for the big wall of text.
If subqueries in where statements work how I remember:
select *
from
Compensation
left join
Link
on Compensation.CompensationID = Link.CompensationID
where
Link.CustomerID = :A
AND (
Link.Sequential = 0
OR
Link.Sequential = (
select MAX(Sequential) from Link where Link.CustomerID = :A
)
)
Try
SELECT c.*
FROM Compensation c
JOIN (select CompensationID, MAX(Sequential) AS LastSeq FROM Link GROUP BY CompensationID) AS LastOnes ON c.ID = LastOnes.CompensationID
JOIN (select CompensationID FROM Link WHERE CustomerID=A AND Sequential=0) AS FirststOnes ON c.ID = FirststOnes.CompensationID
JOIN Link AS l on l.CompensationID=c.CompensationID AND l.CustomerID=A AND l.Sequential=LastOnes.LastSeq
Related
Env: Oracle APEX v5.1 with Oracle 12c Release 2
Firstly, I have created an Interactive Grid that isn't based off an underlying table as I will process this manually using PL/SQL.
I have been using the following as a guide:
https://apex.oracle.com/pls/apex/germancommunities/apexcommunity/tipp/6361/index-en.html
I basically have the following query:
select
level as id,
level as grid_row,
null as product,
null as product_item
from dual connect by level <= 1
Concentrating on just the product and product_item columns where the product_item column will be a readonly column and only the product number can be entered, I would like to achieve the following:
Product Product Item
---------- -------------
123456 123456-1
123456 123456-2
556677 556677-1
654321 654321-1
654321 654321-2
654321 654321-3
123456 123456-3
From the above, as the user types in the Product and then tabs out of the field, I would like a DA to fire that will add the sequence of "-1" to the end of that product number. Then is the user then adds another row within the IG and enters the same product number, I then want it to append "-2" to the end of it.
Only when the product changes number, I need the sequence to reset to "-1" for that new product as per 556677 and so forth.
Other scenarios that should also be taken into consideration are as follows:
From above IG, the user entered 123456 again but this should calculate that the next sequence for 123456 is "-3"
The same needs to be catered for, when a Product is removed from the IG but to always look at the max sequence number for that product.
I was thinking of possibly using APEX_COLLECTIONS as a means of storing what is currently in the grid, since no changes have been committed to the database.
Assuming you have a collection of product values (in this case, I am using the built-in SYS.ODCINUMBERLIST which is a VARRAY data type) then the SQL for your output would be:
SELECT id,
id AS grid_row,
product,
product || '-' || ROW_NUMBER() OVER ( PARTITION BY product ORDER BY id )
AS product_item
FROM (
SELECT ROWNUM AS id,
COLUMN_VALUE AS product
FROM TABLE(
SYS.ODCINUMBERLIST(
123456,
123456,
556677,
654321,
654321,
654321,
123456
)
)
)
ORDER BY id
Output:
ID | GRID_ROW | PRODUCT | PRODUCT_ITEM
-: | -------: | ------: | :-----------
1 | 1 | 123456 | 123456-1
2 | 2 | 123456 | 123456-2
3 | 3 | 556677 | 556677-1
4 | 4 | 654321 | 654321-1
5 | 5 | 654321 | 654321-2
6 | 6 | 654321 | 654321-3
7 | 7 | 123456 | 123456-3
db<>fiddle here
As you mentioned, the data you enter is not saved into the DB whilst you are inserting your products, so it is not in fact stored anywhere.
So you cannot go check if that value already exists and enter a -2 or other.
Some things to consider would be to maybe save the values into a temp table so you can then have a function go check how many product_item like 123456-% are in there and use that number +1 as your new product_item.
Or you could go the even harder way and do it all with javascript. For this you will need to somehow get all records in the IG, go through them all and see how many occurences of 123456 you have and then insert 123456-(no of occurences + 1).
How can I create a column that has ranked the information of the table based on two or three keys?
For example, in this table the rank variable is based on Department and Name:
Dep | Name | Rank
----+------+------
1 | Jeff | 1
1 | Jeff | 2
1 | Paul | 1
2 | Nick | 1
2 | Nick | 2
I have found this solution but it's in SQL and I don't think it applies to my case as all information is in one table and the responses seem to SELECT and JOIN combine information from different tables.
Thank you in advance
You can count how many rows come before the current row in the current group:
UPDATE MyTable
SET Rank = (SELECT COUNT(*)
FROM MyTable AS T2
WHERE T2.Dep = MyTable.Dep
AND T2.Name = MyTable.Name
AND T2.rowid <= MyTable.rowid);
(The rowid column is used to differentiate between otherwise identical rows. Use the primary key, if you have one.)
I currently have a table in SQLite that looks something like the following, forming a tree-like structure:
+-----+-----------+---------------+
| _id | parent_id | tree_depth |
+=====+===========+===============+
| 1 | 0 | 0 |
| 2 | 1 | (should be 1) |
| 3 | 2 | (should be 2) |
+-----+-----------+---------------+
I have very limited SQLite experience and the table is quite large, so I would hate to have to fill it out manually. Is there a query I could use to update the tree_depth column such that it properly represents the depth of the tree at that node? I tried selecting the parent's tree depth and incrementing, but for some reason it set everything to 1.
Any advise would be greatly appreciated.
EDIT: The query that I'm trying is:
UPDATE table SET tree_depth = (SELECT p.tree_depth FROM table JOIN table p ON p._id=table.parent_id) +1
You need a recursive CTE to compute the tree depth of each entry.
You can then use this data to look up the value to UPDATE:
WITH RECURSIVE depths(id, depth) AS (
SELECT _id, 0
FROM MyTable
WHERE parent_id = 0
UNION ALL
SELECT MyTable._id, depths.depth + 1
FROM MyTable
JOIN depths ON MyTable.parent_id = depths.id
)
UPDATE MyTable
SET tree_depth = (SELECT depth
FROM depths
WHERE depths.id = MyTable._id);
(Note: older Android versions do not support CTEs.)
Please try?
update table
set a.tree_depth = b.parent_id
If it doesn't wok, try to add this too:
FROM table a
INNER JOIN table b
on a._id= b._id
I have 2 table one table is Course Category and second is Course
In Course Category Table
Following data stores :
CategoryId | Name
1 | MCA
2 | MBA
In Course Table
Following data stores :
Id | Name | CategoryId | ParentId
1 | Asp.Net | 1 | 0
2 | C# | 1 | 1
3 | Finance | 2 | 0
i want following output
Id | Name | Parent
1 | MCA | 0
2 | MBA | 0
3 | Asp.Net | 1
4 | C# | 3
5 | Finance | 2
Whether i have to use nested query or should i relate two tables with foreign and primary keys or any mapping should be done.if not give me a solution to do this.
thanks in advance
select rownum as id, name, 0 as parent
from Category
union all
select rownum, name, id
from course
I assume that you only have one level of children (no cases like parent<-child<-child)
select c.id, t.name, parent.name, c.name from course c
join category t on c.categoryId = t.id
left join (select c2.id, c2.name from course c2) parent on c.parentId = parent.id
This should give you something like
id |categoryname |parentname |coursename
1 |MCA |null |Asp.Net
2 |MCA |Asp.Net |C#
3 |MBA |null |Finance
This is not exactly your desired result but should do the trick to display what you want.
I read many questions here about mutual friends and following and followers but i can't solved my problem, I have two tables like these.
User_table ( UID, Name)
Relation_table (RID, UID,UIDF)
for example in user_table have 4 users
UID | Name
------------------
1 | Kim Tessman
2 | Nella Ohler
3 | Adria Larose
4 | Huey Errico
And Relation_table have these data
RID | UID | UIDF
------------------
1 | 1 | 2
2 | 2 | 1
3 | 1 | 4
4 | 4 | 3
5 | 4 | 1
my questions are :
how to get list of Mutual friends ?
how to get list of Following ?
how to get list of Followers ?
please who can solve this problem thank you :)
I am guessing that the UID column in the Relation_Table is the user and that the UIDF is the person they are following. Here is the SQL query that finds who a person is following. The who is being followed is the same query, you just focus on the other name column or switch the column order around.
Here is a list of who follows who. It is also the list of who is being followed.
SELECT FollowingUser.UID as FollowingUserID, FollowingUser.Name, BeingFollowed.UID AS BeingFollowedID, BeingFollowed.Name AS BeingFollowedName
FROM User_table AS FollowingUser INNER JOIN
Relation_Table AS r ON FollowingUser.UID = r.uid INNER JOIN
User_table AS BeingFollowed ON r.uidf = BeingFollowed.UID
And this query gives you the list of mutual friends - but it gives the inverse of the relationship. If this matters, add this to the end where FollowingUser.UID > BeingFollowed.UID
SELECT FollowingUser.UID AS FollowingUserID, FollowingUser.Name, BeingFollowed.UID AS BeingFollowedID, BeingFollowed.Name AS BeingFollowedName
FROM User_table AS FollowingUser INNER JOIN
Relation_Table AS r ON FollowingUser.UID = r.uid INNER JOIN
Relation_Table AS r1 ON r.uid = r1.uidf AND r.uidf = r1.uid INNER JOIN
User_table AS BeingFollowed ON r1.uid = BeingFollowed.UID