So i have the following two tables (simplified):
Table 1: FOLDERS
ID | DESC_FOLDER | TEMPLATE_ID
---------------------------------
... | ... | ...
20 | Folder 1 | 52
21 | Folder 2 | 55
... | | ...
Table 2: TEMPLATES
ID | DESC_TEMPLATE | GROUP
-----------------------------
... | ... | ...
51 | Template 1 | abc
52 | Template 2 | abc
53 | Template 3 | abc
54 | Template 4 | abc
55 | Template 5 | NULL
... | ... | ...
The result should be a list with all the templates and their corresponding folder.
Expected Result:
DESC_TEMPLATE | DESC_FOLDER
---------------------------
Template 1 | Folder 1
Template 2 | Folder 1
Template 3 | Folder 1
Template 4 | Folder 1
Template 5 | Folder 2
I have problems with the grouped templates, because only one template of each group is connected to the folder. The following sql command obviously only returns the templates directly connected to the folder. How to extend my command to get the desired output?
Select
T.DESC_TEMPLATE,
F.DESC_FOLDER
from
TEMPLATES T,
FOLDERS F
where
T.ID = F.TEMPLATE_ID
Thanks a lot for your help!
I think a window function will solve your problem:
Select T.DESC_TEMPLATE,
MAX(F.DESC_FOLDER) OVER (PARTITION BY t.GROUP) as DESC_FOLDER
from TEMPLATES T left join
FOLDERS F
on T.ID = F.TEMPLATE_ID;
where
T.ID = F.TEMPLATE_ID (+)
Related
I'm bit confused with this problem, I have following table called Member and its structure as follows,
+----------+------+-------------+
| MemberID | Name | ActiveState |
+----------+------+-------------+
| 1 | PAUL | 1 |
+----------+------+-------------+
| 2 | JHON | 1 |
+----------+------+-------------+
| 3 | AMBE | 0 |
+----------+------+-------------+
| 4 | NISH | 1 |
+----------+------+-------------+
And I have another table called ServiceProvided. and its structure as follows. All the member provided data will be saved in this table.
+--------------+-------------+------------+
| ServiceProID | Fkserviceid | FkMemberID |
+--------------+-------------+------------+
| 1 | S1 | 1 |
+--------------+-------------+------------+
| 2 | S2 | 1 |
+--------------+-------------+------------+
| 3 | S1 | 2 |
+--------------+-------------+------------+
| 4 | S3 | 2 |
+--------------+-------------+------------+
Application can soft delete members by changing their active state to 0. I need to get all the ActiveState = 1members data and need to get only if that member has provided any service in the past, should his data be retrieved even if he is deleted. How can I do it.
Expected output is,
ActiveState = 1 and ActiveState = 0 members who has only provided any service in the past
SELECT m.*
FROM Member m
WHERE m.ActiveState = 1
UNION
SELECT m.*
FROM Member m
INNER JOIN ServiceProvided s ON m.MemberId = s.FkMemberId
WHERE m.ActiveState = 0;
The easiest way to achieve this is with UNION.
The INNER JOIN on the deleted Member query assures that you will not retrieve a Member who lacks entries in ServiceProvided.
I try to create a json select query which can give me back the result on next way.
1 row contains 1 main_message_id and belonging messages. (Like the bottom image.) The json format is not a requirement, if its work with other methods, it will be fine.
I store the data as like this:
+-----------------+---------+----------------+
| main_message_id | message | sub_message_id |
+-----------------+---------+----------------+
| 1 | test 1 | 1 |
| 1 | test 2 | 2 |
| 1 | test 3 | 3 |
| 2 | test 4 | 4 |
| 2 | test 5 | 5 |
| 3 | test 6 | 6 |
+-----------------+---------+----------------+
I would like to create a query, which give me back the data as like this:
+-----------------+-----------------------+--+
| main_message_id | message | |
+-----------------+-----------------------+--+
| 1 | {test1}{test2}{test3} | |
| 2 | {test4}{test5}{test6} | |
| 3 | {test7}{test8}{test9} | |
+-----------------+-----------------------+--+
You can use json_agg() for that:
select main_message_id, json_agg(message) as messages
from the_table
group by main_message_id;
Note that {test1}{test2}{test3} is invalid JSON, the above will return a valid JSON array e.g. ["test1", "test2", "test3"]
If you just want a comma separated list, use string_agg();
select main_message_id, string_ag(message, ', ') as messages
from the_table
group by main_message_id;
I am creating a web based file explorer where the details of files and folders are stored in the database and are shared with Active Directory users or groups. When I have to bind the grid with shared files, it takes a lot of time if files are more because I first fetch all the files and then remove the subfiles / subdirectories rows. How can I ignore the subfiles / subdirectories so that the performance will increase?
This is a sample table of the files to which the user has permissions.
id | path | name | parent | isdirectory
-----------------------------------------------------------------------------------------------------------------
1 | /data/user1/folder1 | folder1 | /data/user1 | true
2 | /data/user1/folder1/text1.txt | text1.txt | /data/user1/folder1 | false
3 | /data/user1/folder1/folder2 | folder2 | /data/user1/folder1 | true
4 | /data/user1/folder1/folder2/text2.txt | text2.txt | /data/user1/folder1/folder2 | false
5 | /data/user2/paper.pdf | paper.pdf | /data/user2 | false
5 | /data2/backup/reports | reports | /data2/backup | true
6 | /data2/backup/reports/rep1.pdf | rep1.pdf | /data2/backup/reports | false
7 | /softwaredump | softwaredump | / | true
8 | /softwaredump/win10.iso | win10.iso | /softwaredump | false
Now as you can see that there are subfiles and folders in this table. So while binding the grid, I use this query
WITH finally AS
(SELECT DISTINCT
Parent
FROM
files m1
WHERE Parent NOT IN (
SELECT Path FROM files WHERE Path LIKE CONCAT(#Path,'/%')
)
)
SELECT *
FROM files fin
INNER JOIN finally ON finally.Parent = fin.Parent
WHERE fin.Path LIKE CONCAT(#Path,'/%')
Here #Path is the SP Parameter to browse the path, default being '' and later on say '/data/user1/folder1' for browsing that folder
Expected output as I am getting.
id | path | name | parent | isdirectory
-----------------------------------------------------------------------------------------------------------------
1 | /data/user1/folder1 | folder1 | /data/user1 | true
5 | /data/user2/paper.pdf | paper.pdf | /data/user2 | false
5 | /data2/backup/reports | reports | /data2/backup | true
7 | /softwaredump | softwaredump | / | true
I have also added a Non-clustered index. For about 15000 files, this query takes about 20-30 seconds.
However, as number of files increase, the performance decreases. The solution for that would be to select only the top most level and ignore the subfiles and subfolders. But when a file is shared, it becomes the topmost level and it has no sublevel.
Here is a sample SQLFiddle.
I am working with some tables that represent a file system, and I need to select the full path of each folder as a flattened string.
The first table lists the details of each folder:
CREATE TABLE Folders(
FolderID int IDENTITY(1,1) NOT NULL,
[Name] nvarchar(255) NOT NULL)
The second table lists transitive closures of folder relationships:
CREATE TABLE FolderClosures(
FolderClosuresID int IDENTITY(1,1) NOT NULL,
AncestorFolderID int NOT NULL, --Foreign key to Folders.FolderID
DescendantFolderID int NOT NULL --Foreign key to Folders.FolderID
IsDirect bit NOT NULL)
For sample data, let's assume the following folders exist:
Documents/
Documents/Finance/
Documents/HumanResources/
Documents/HumanResources/Training/
These would be persisted in those tables as follows:
| FolderID | Name |
+----------+----------------+
| 1 | Documents |
| 2 | Finance |
| 3 | HumanResources |
| 4 | Training |
| FolderClosureID | AncestorFolderID | DescendantFolderID | IsDirect |
+-----------------+------------------+--------------------+----------+
| 1 | 1 | 1 | 0 |
| 2 | 2 | 2 | 0 |
| 3 | 1 | 2 | 1 |
| 4 | 3 | 3 | 0 |
| 5 | 1 | 3 | 1 |
| 6 | 4 | 4 | 0 |
| 7 | 1 | 4 | 0 |
| 8 | 3 | 4 | 1 |
Some details to note:
Every folder has an "identity row" in FolderClosures, where AncestorFolderID = DescendantFolderID AND IsDirect = 0.
Every folder that is not a top-level folder has exactly one row in FolderClosures where IsDirect = 1
FolderClosures can contain many rows per folder, where AncestorFolderID <> DescendantFolderID AND IsDirect = 0. Each of these represents a "grandparent" or more distant relationship.
Since no columns are nullable, no rows explicitly state that a given folder is a top-level folder. This can only be discerned by checking that there are no rows in FolderClosures where IsDirect = 1 AND DescendantFolderID = SomeID where SomeID is the ID of the folder in question.
I want to be able to run a query that returns this data:
| FolderID | Path |
+----------+------------------------------------+
| 1 | Documents/ |
| 2 | Documents/Finance/ |
| 3 | Documents/HumanResources/ |
| 4 | Documents/HumanResources/Training/ |
Folders may be nested at unlimited depth, but realistically probably only up to 10 levels. Queries may require returning paths for a few thousand folders.
I've found a lot of advice on creating this type of query when data is persisted as an adjacency list, but I haven't been able to find an answer for a transitive closure setup like this. The adjacency list solutions I've found rely on rows being persisted with nullable parent folder IDs, but that doesn't work here.
How can I get the desired output?
If it helps, I am using SQL Server 2016.
One way to get desired output is to do a recursive query. For this, I think the best is to only use the rows that have IsDirect = 1 and use the anchor as all folders that don't have direct parent in FolderClosures, which should be all your root folders.
WITH FoldersCTE AS (
SELECT F.FolderID, CAST(F.Name as NVARCHAR(max)) Path
FROM Folders F
WHERE NOT EXISTS (
SELECT 1 FROM FolderClosures FC WHERE FC.IsDirect = 1 AND FC.DescendantFolderID = F.FolderID
)
UNION ALL
SELECT F.FolderID, CONCAT(PF.Path, '\', F.Name)
FROM FoldersCTE PF
INNER JOIN FolderClosures FC
ON FC.AncestorFolderID = PF.FolderId
AND FC.IsDirect = 1
INNER JOIN Folders F
ON F.FolderID = FC.DescendantFolderID
)
SELECT *
FROM FoldersCTE
OPTION (MAXRECURSION 1000) --> how many nested levels you think you will have
This produces:
FolderID Path
1 Documents
2 Documents\Finance
3 Documents\HumanResources
4 Documents\HumanResources\Training
Hope it helps.
I need to grab the comments that a user started and which were answered by him.
I'm trying to inner join below, but he repeats the result.
I need to show the User's comment that he started with the answers, and both he replied.
select *
from comments as comment
join comments as parent
on comment.user_parent_id = parent.user_id
where comment.member = 123
user_id | user_fname | user_lname | user_parent_id | member
1 | test 1 | xx | 1 | 123
2 | test 2 | xx | |
3 | test 3 | xx | |
4 | test 4 | xx | 1 | 123
You can make a recursive SQL function, use a hierarchycal index (SQL Server) or make a loop "while has parent".