Select entry with only one entry in many to many relationship - sql

Say I have a database table user_provider, that contains many to many relationship of user and provider table.
I want to get only those userId which is having only one provider
SELECT spr1.SU_URS_ID,count(spr1.SU_URS_ID)
FROM overstappen.spr_usr spr1
WHERE spr1.SU_URS_ID in ( select spr.SU_URS_ID
from overstappen.spr_usr spr
where spr.SU_SPR_ID =40)
GROUP BY spr1.SU_URS_ID;
Above query returns all users which is having SU_SPR_ID 40. And the total no of users with same userId in spr_usr table.
I only want to get user with count 1. i.e user with only one provider.
Thanks in advance.

Try this
SELECT spr1.SU_URS_ID, COUNT(spr1.SU_URS_ID)
FROM overstappen.spr_usr spr1
WHERE spr1.SU_URS_ID IN
(SELECT spr.SU_URS_ID
FROM overstappen.spr_usr spr WHERE spr.SU_SPR_ID =40)
GROUP BY spr1.SU_URS_ID
HAVING COUNT(spr1.SU_URS_ID) = 1

Try adding at the end of your query HAVING COUNT(spr1.SU_URS_ID) = 1:
SELECT spr1.SU_URS_ID,count(spr1.SU_URS_ID)
FROM overstappen.spr_usr spr1
WHERE spr1.SU_URS_ID in (
SELECT spr.SU_URS_ID
FROM overstappen.spr_usr spr
WHERE spr.SU_SPR_ID =40)
GROUP BY spr1.SU_URS_ID
HAVING COUNT(spr1.SU_URS_ID) = 1;

Related

SQL - How to insert into table based on id's found in another table?

I would need something like this pseudo code:
I think you are probably looking for something like
INSERT INTO userauthorizations
SELECT DISTINCT userid, 11
FROM userauthorizations ua1
WHERE NOT EXISTS
(SELECT *
FROM userauthorizations ua2
WHERE ua2.userid = ua1.userid
AND ua2.authid = 11)
This will find all users who do not currently have a authid=11 and add a row for that userid with authid=11.
Note that this is different from your pseudocode (SELECT DISTINCT USERID FROM USERAUTHORIZATIONS WHERE AUTHID <> 11), which finds users who have at least one entry that isn't authid=11.

How to give access and partial access to specifc Users in ORACLE database

I am trying to create a view in an Oracle database whereby if a USER is in the PLAYER field of the base table, only the rows of this player are outputted, but if a USER matches the MANAGER role of another base table, all rows of this first base table are outputted.
So far I have this which I'm not sure even works?
CREATE VIEW Player_view AS
SELECT (CASE WHEN USER IN PT.PLAYER THEN (SELECT * FROM PT WHERE USER = PT.PLAYER)
ELSE WHEN USER IN PM.MANAGER THEN (SELECT * FROM PT)
END
FROM Player_Table PT, Player_Managers PM
Otherwise, I have tried with grant permissions - however, how do I give grant permission to SELECT over just one row vs. all rows?
Probably something like the following should suffice
create view player_view as
select * from player_table
where player = user
union all
select * from player_table
where exists ( select 1 from player_manager where manager = user )
If the two are not mutually exclusive, then you could add a 'not exists' to the second query
create view player_view as
select * from player_table
where player = user
union all
select * from player_table
where exists ( select 1 from player_manager where manager = user )
and player != user

Getting rid of the "where" clause if a value = 'ADMIN'

So there is the main table (named Table1) and one of the columns in that table has a column called company name. and there's a another table called Account and in that table it has the usernames of people and the company name that user is associated with. so only the information in table1 associated with the user's company should be shown, unless if they're an admin.
I'm working on an APEX app on Oracle
I currently have a query that looks like this:
Select
SUPPLIER,
sum(NUMBER_OF_TICKETS) TICKETS,
round((sum(NUMBER_OF_TICKETS*AMOUNT_PAYABLE__FOREIGN_CUR)*.1),2) COMMISION,
round(sum(NUMBER_OF_TICKETS*AMOUNT_PAYABLE__FOREIGN_CUR),2) TOTAL_SALES,
round((sum(NUMBER_OF_TICKETS*AMOUNT_PAYABLE__FOREIGN_CUR)-(sum(NUMBER_OF_TICKETS*AMOUNT_PAYABLE__FOREIGN_CUR)*.1)),2) COMPANY_OWE,
CURRENCY
FROM TABLE1
WHERE
Supplier = (select COMPANYNAME from Account where lower(USERNAME)=lower(:APP_USER)) AND
PURCHASE_DATE_AND_TIME >= TO_DATE(:P2_START)
AND PURCHASE_DATE_AND_TIME < TO_DATE(:P2_END)+ 1
group by
SUPPLIER,
CURRENCY
I'm running into trouble with the "WHERE" function.
Because I basically want to have a if...then... (or a case statement in this case)
where
IF
((select COMPANYNAME from Account where lower(USERNAME)=lower(:APP_USER)) == 'COMPANY1' AND (select USERTYPE from Account where lower(USERNAME)=lower(:APP_USER)) == 'ADMIN')
THEN
show all the rows; aka, Supplier = (select COMPANYNAME from BBAccount where lower(USERNAME)=lower(:APP_USER)) in the query
Does anyone have any ideas on how to go about writing a query for this?
I tried doing
Case statement When statement Then NULL
It doesn't work
I tried drawing a diagram, let me know if this makes it more clear:
Diagram
As it is about Apex, I'd suggest you to create a function:
create or replace function f_is_admin_01 (par_app_user in varchar2)
return number
is
-- function returns 1 if PAR_APP_USER is admin; otherwise, it returns 0
l_usertype account.usertype%type;
begin
select a.usertype
into l_usertype
from account a
where lower(a.username) = lower(par_app_user);
return case when l_usertype = 'ADMIN' then 1
else 0
end;
exception
when no_data_found then
return 0;
end;
Now, you can use it in query as
select ...
from account a join table1 t on a.companyname = t.companyname
where (lower(a.username) = lower(:APP_USER) or f_is_admin_01 (:APP_USER) = 1)
and t.purchasedate ...
Such an approach (I mean, having a function) can be useful elsewhere; for example, if you want to show certain page region only to admins - you'd put
return f_is_admin_01(:APP_USER) = 1;
into region's "Server side condition" (its type would be "Function that returns Boolean").
See if it helps.
So there is the main table (named Table1) and one of the columns in that table has a column called company name. and there's a another table called Account and in that table it has the usernames of people and the company name that user is associated with. so only the information in table1 associated with the user's company should be shown, unless if they're an admin
I think that you could simply join - something like:
SELECT ...
FROM TABLE1 t
INNER JOIN ACCOUNTS a
ON lower(a.username) = lower(:APP_USER)
AND (a.companyname = t.companyname OR a.usertype = 'ADMIN')
WHERE
t.purchase_date_and_time >= TO_DATE(:P2_START)
AND t.purchase_date_and_time < TO_DATE(:P2_END) + 1
GROUP BY ...
The inner join on ACCOUNTS is there to implement the filtering logic: the user must either the user belongs to the same company, or have the admin type.
EXISTS(...) is your friend:
Select SUPPLIER
,sum(NUMBER_OF_TICKETS) TICKETS
,round((sum(NUMBER_OF_TICKETS*AMOUNT_PAYABLE__FOREIGN_CUR)*.1),2) COMMISION
,round(sum(NUMBER_OF_TICKETS*AMOUNT_PAYABLE__FOREIGN_CUR),2) TOTAL_SALES
,round((sum(NUMBER_OF_TICKETS*AMOUNT_PAYABLE__FOREIGN_CUR)
-(sum(NUMBER_OF_TICKETS*AMOUNT_PAYABLE__FOREIGN_CUR)*.1)),2) COMPANY_OWE
, CURRENCY
FROM TABLE1 t
WHERE EXISTS (
SELECT 1
from Account x
where x.Supplier = t.COMPANYNAME
AND lower(x.USERNAME) = lower(:APP_USER))
AND x.PURCHASE_DATE_AND_TIME >= TO_DATE(:P2_START)
AND x.PURCHASE_DATE_AND_TIME < TO_DATE(:P2_END)+ 1
)
group by SUPPLIER, CURRENCY
;

How to get one common value from Database using UNION

2 records in above image are from Db, in above table Constraint are (SID and LINE_ITEM_ID),
SID and LINE_ITEM_ID both column are used to find a unique record.
My issues :
I am looking for a query it should fetch the recored from DB depending on conditions
if i search for PART_NUMBER = 'PAU43-IMB-P6'
1. it should fetch one record from DB if search for PART_NUMBER = 'PAU43-IMB-P6', no mater to which SID that item belong to if there is only one recored either under SID =1 or SID = 2.
2. it should fetch one record which is under SID = 2 only, from DB on search for PART_NUMBER = 'PAU43-IMB-P6', if there are 2 items one in SID=1 and other in SID=2.
i am looking for a query which will search for a given part_number depending on Both SID 1 and 2, and it should return value under SID =2 and it can return value under SID=1 only if the there are no records under SID=2 (query has to withstand a load of Million record search).
Thank you
Select *
from Table
where SID||LINE_ITEM_ID = (
select Max(SID)||Max(LINE_ITEM_ID)
from table
where PART_NUMBER = 'PAU43-IMB-P6'
);
If I understand correctly, for each considered LINE_ITEM_ID you want to return only the one with the largest value for SID. This is a common requirement and, as with most things in SQL, can be written in many different ways; the best performing will depend on many factors, not least of which is the SQL product you are using.
Here's one possible approach:
SELECT DISTINCT * -- use a column list
FROM YourTable AS T1
INNER JOIN (
SELECT T2.LINE_ITEM_ID,
MAX(T2.SID) AS max_SID
FROM YourTable AS T2
GROUP
BY T2.LINE_ITEM_ID
) AS DT1 (LINE_ITEM_ID, max_SID)
ON T1.LINE_ITEM_ID = DT1.LINE_ITEM_ID
AND T1.SID = DT1.max_SID;
That said, I don't recall seeing one that relies on the UNION relational operator. You could easily rewrite the above using the INTERSECT relational operator but it would be more verbose.
Well in my case it worked something like this:
select LINE_ITEM_ID,SID,price_1,part_number from (
(select LINE_ITEM_ID,SID,price_1,part_number from Table where SID = 2)
UNION
(select LINE_ITEM_ID,SID,price_1,part_number from Table SID = 1 and line_item_id NOT IN (select LINE_ITEM_ID,SID,price_1,part_number from Table SID = 2)))
This query solved my issue..........

Fetch top X users, plus a specific user (if they're not in the top X)

I have a list of ranked users, and would like to select the top 50. I also want to make sure one particular user is in this result set, even if they aren't in the top 50. Is there a sensible way to do this in a single mysql query? Or should I just check the results for the particular user and fetch him separately, if necessary?
Thanks!
If I understand correctly, you could do:
select * from users order by max(rank) desc limit 0, 49
union
select * from users where user = x
This way you get 49 top users plus your particular user.
Regardless if a single, fancy SQL query could be made, the most maintainable code would probably be two queries:
select user from users where id = "fred";
select user from users where id != "fred" order by rank limit 49;
Of course "fred" (or whomever) would usually be replaced by a placeholder but the specifics depend on the environment.
declare #topUsers table(
userId int primary key,
username varchar(25)
)
insert into #topUsers
select top 50
userId,
userName
from Users
order by rank desc
insert into #topUsers
select
userID,
userName
from Users
where userID = 1234 --userID of special user
select * from #topUsers
The simplest solution depends on your requirements, and what your database supports.
If you don't mind the possibility of having duplicate results, then a simple union (as Mariano Conti demonstrated) is fine.
Otherwise, you could do something like
select distinct <columnlist>
from (select * from users order by max(rank) desc limit 0, 49
union
select * from users where user = x)
if you database supports it.