Comma separated column values in a laravel join query - sql

I have a laravel webapp in which my database is structured via the below tables. The relationship is that transactions hasmany loading_hire_agreements via lhas_transactions.
Table name: transactions
| id | date | number |
|----|-------------------|--------|
| 1 | 12:00:00 00:00:00 | TRN#1 |
| 2 | 10:00:00 00:00:00 | TRN#2 |
Table name: loading_hire_agreements
| id | number |
|----|--------|
| 1 | JY1001 |
| 2 | JY1002 |
| 3 | JY1003 |
Table name: lhas_transactions
| transction_id | lha_id |
|---------------|--------|
| 1 | 1 |
| 1 | 2 |
| 2 | 3 |
I want to write a join statement using laravel's DB:table()->join(\* any relevant join *\) so that the below output is generated.
| transactions.id | transactions.number | loading_hire_agreements.number |
|------------------|---------------------|--------------------------------|
| 1 | TRN#1 | JY1001, JY1002 |
| 2 | TRN#2 | JY1003 |
I "have" to use DB:table() because I am connecting this query to a front-end datatable service.

Try using GROUP_CONCAT and join all three tables:
$users = DB::table('transactions')
->join('lhas_transactions as lt', 'transactions.id', '=', 'lt.transaction_id')
->join('loading_hire_agreements as lha', 'lt.lha_id', '=', 'lha.id')
->select(DB::raw('transactions.id, transactions.number, GROUP_CONCAT(lha.number ORDER BY lha.id) AS agreements'))
->groupBy('transactions.id', 'transactions.number')
->get();

Related

postgresql & json - counting distinct values

In PostgreSQL, I have a table that looks like,
| id | json |
| -- | ------------------------------- |
| 1 | {"id":1,"customer":"BANK"} |
| 1 | {"id":1,"customer":"BANK"} |
| 2 | {"id":2,"customer":"GOVT"} |
| 3 | {"id":3,"customer":"BANK"} |
| 4 | {"id":4,"customer":"ASSET MGR"} |
| 4 | {"id":4,"customer":"ASSET MGR"} |
I need the output of counting the occurrences of customers with unique ids, such as
| customer | count |
| ----------- | ----- |
| "BANK" | 2 |
| "GOVT" | 1 |
| "ASSET MGR" | 1 |
Is there a good way to achieve using PostgreSQL & json? I currently am able to extract the customer and IDs, but am having difficulty counting the unique json objects.
select count(distinct id), jsondata ->> 'customer' customer
from data
group by customer
count | customer
----: | :--------
1 | ASSET MGR
2 | BANK
1 | GOVT
db<>fiddle here

Sql server : select members having 2 or more records on different date of same class

I am trying to find out all the member ids who have more than 2 records on a different dates in the same class.
+----------+------------+-------+-----------+
| MemberId | Date | Class | |
+----------+------------+-------+-----------+
| 118111 | 2/18/2020 | A | Valid |
| 118111 | 10/15/2020 | A | Valid |
| 118216 | 1/31/2020 | B | Valid |
| 118216 | 5/16/1981 | B | Valid |
| 118291 | 6/9/2020 | A | Valid |
| 118291 | 12/5/2020 | A | Valid |
| 118533 | 4/9/2020 | A | Not valid |
| 118533 | 11/11/2020 | B | Not valid |
| 118533 | 7/22/2020 | C | Valid |
| 118533 | 10/25/2020 | C | Valid |
| 118293 | 3/30/2020 | A | Not valid |
| 118293 | 3/30/2020 | A | Not valid |
| 118499 | 4/16/2020 | B | Valid |
| 118499 | 7/26/2020 | B | Valid |
| 118499 | 3/25/2020 | A | Not valid |
+----------+------------+-------+-----------+
I have made a query which checks only 2 records but unable to find a solution for checking more than 2 records.
select mc.*
FROM table1 AS mc
JOIN table1 AS ma ON ma.memberid = mc.memberid
AND ma.date != mc.date
AND ma.class = mc.class
Assuming you just want the memberid you can us a HAVING:
SELECT memberid
FROM dbo.YourTable
GROUP BY memberid
HAVING COUNT(DISTINCT [Date]) > 2;

Row Level Security with multiple users for one row

I'm trying to implement Row Level Security in SQL Server 2016.
The problem is, I can have multiple users that should have read permissions over given rows, and when I write some complex condition in the predicate the performance gets like very very very bad.
I tried to keep all usernames in one column of the table and in the predicate to search through them for the SYSTEM_USER with % LIKE % but performance is low.
Example of the values in the Usernames column in my controlled table for one row:
domain\john.wick;domain\red.eagle;domain\spartak.something....
Here is my function:
CREATE FUNCTION fn_securitypredicate(#Usernames AS nvarchar(4000))
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN
SELECT 1 as Result
WHERE #Usernames LIKE '%' + SYSTEM_USER + '%'
With this execution time from 2 sec became 50 sec. Any suggestions for improvement.
CREATE SECURITY POLICY [Policy]
ADD FILTER PREDICATE [fn_securitypredicate]([Usernames])
ON [dbo].[Products];
This is the solution I came up with for my previous team.
This requires a a users table, a users permissions table as well as a permission column on your controlled table. It should also have a user group and user group permissions table to scale with users.
users user_permissions controlled_table
+-----------+---------+ +---------+---------------+ +---------------+------+------+
| user_name | user_id | | user_id | permission_id | | permission_id | pk_1 | pk_2 |
+-----------+---------+ +---------+---------------+ +---------------+------+------+
| admin | 1 | | 1 | 0 | | 2 | 1 | 1 |
| user1 | 2 | | 2 | 1 | | 2 | 1 | 2 |
| user2 | 3 | | 2 | 2 | | 3 | 1 | 3 |
| user3 | 4 | | 2 | 3 | | 4 | 2 | 1 |
| | | | 2 | 4 | | 3 | 2 | 2 |
| | | | 3 | 1 | | 1 | 2 | 3 |
| | | | 3 | 2 | | 1 | 3 | 1 |
| | | | 4 | 2 | | 5 | 3 | 2 |
| | | | 4 | 3 | | 4 | 3 | 3 |
| | | | 4 | 4 | | 2 | 4 | 1 |
| | | | | | | 3 | 4 | 2 |
| | | | | | | 3 | 4 | 3 |
+-----------+---------+ +---------+---------------+ +---------------+------+------+
For performance, you will want to add the permission_id to whatever index you were using to search the controlled table. This will allow you to join permissions on the index while searching on the remaining columns. You should view the execution plan for specific details on your indexes.

SQL Get cases related to a user and the number of files attached to that case

Hi everyone got a little stuck on an sql query. I have four tables
users
+----+------------+-----------+--------+
| id | first_name | last_name | active |
+----+------------+-----------+--------+
| 1 | Joe | Bloggs | 1 |
| 2 | John | Doe | 1 |
| 3 | Dave | Smith | 1 |
+----+------------+-----------+--------+
cases
+----+-----------+-------------+
| id | case_code | case_name |
+----+-----------+-------------+
| 1 | THEC12C | Test Case 1 |
| 2 | ABCD23A | Test Case 2 |
+----+-----------+-------------+
case_creditors
+----+---------+-------------+
| id | case_id | creditor_id |
+----+---------+-------------+
| 1 | 1 | 3 |
| 2 | 2 | 1 |
+----+---------+-------------+
case_files
+----+---------+----------+-----------+
| id | case_id | filename | file type |
+----+---------+----------+-----------+
| 1 | 1 | test.pdf | pfd |
| 2 | 2 | file.txt | txt |
| 3 | 2 | word.doc | doc |
+----+---------+----------+-----------+
When a user logs in i need to show a table with the users accociated cases the number of files attached to that case so if Joe Blogs loged in head see the following table
+-----------+-------------+-------+
| Case Code | Case Name | Files |
+-----------+-------------+-------+
| ABCD23A | Test Case 2 | 2 |
+-----------+-------------+-------+
ive been trying to write the sql statement to do this but am getting stuck on the query and wandered if someone could help give me some pointers. the sql ive gor so far
SELECT * FROM cases
(SELECT COUNT(*) FROM case_files WHERE case_files.case_id = cases.id) as Files
JOIN case_creditors ON cases.id = case_creditors.case_id
WHERE case_creditors.creditor_id = 1
managed to sort this with
SELECT
ips_case.*,
COUNT(case_files.file_id) AS Files
FROM
ips_case
LEFT JOIN case_files ON ips_case.id = case_files.case_id
JOIN case_creditors ON ips_case.id = case_creditors.case_id
WHERE
case_creditors.creditors_id = 4
GROUP BY
ips_case.id

Selecting all rows in a master table and summing columns in multiple detail tables

I have a master table (Project List) along with several sub tables that are joined on one common field (RecNum). I need to get totals for all of the sub tables, by column and am not sure how to do it. This is a sample of the table design. There are more columns in each table (I need to pull * from "Project List") but I'm showing a sampling of the column names and values to get an idea of what to do.
Project List
| RecNum | Project Description |
| 6 | Sample description |
| 7 | Another sample |
WeekA
| RecNum | UserName | Day1Reg | Day1OT | Day2Reg | Day2OT | Day3Reg | Day3OT |
| 6 | JustMe | 1 | 2 | 3 | 4 | 5 | 6 |
| 6 | NotMe | 1 | 2 | 3 | 4 | 5 | 6 |
| 7 | JustMe | | | | | | |
| 7 | NotMe | | | | | | |
WeekB
| RecNum | UserName | Day1Reg | Day1OT | Day2Reg | Day2OT | Day3Reg | Day3OT |
| 6 | JustMe | 7 | 8 | 1 | 2 | 3 | 4 |
| 6 | NotMe | 7 | 8 | 1 | 2 | 3 | 4 |
| 7 | JustMe | | | | | | |
| 7 | NotMe | | | | | | |
So the first query should return the complete totals for both users, like this:
| RecNum | Project Description | sumReg | sumOT |
| 6 | Sample description | 40 | 52 |
| 7 | Another sample | 0 | 0 |
The second query should return the totals for just a specified user, (WHERE UserName = 'JustMe') like this:
| RecNum | Project Description | sumReg | sumOT |
| 6 | Sample description | 20 | 26 |
| 7 | Another sample | 0 | 0 |
Multiple parallel tables with the same structure is usually a sign of poor database design. The data should really be all in one table, with additional columns specifying the week.
You can, however, use union all to bring the data together. The following is an example of a query:
select pl.recNum, pl.ProjectDescription,
sum(Day1Reg + Day2Reg + Day3Reg) as reg,
sum(Day1OT + Day2OT + Day3OT) as ot
from ProjectList pl join
(select * from weekA union all
select * from weekB
) w
on pl.recNum = w.recNum
group by l.recNum, pl.ProjectDescription,;
In practice, you should use select * with union all. You should list the columns out explicitly. You can add appropraite where clauses or conditional aggregation to get the results you want in any particular case.