How to bypass records with case - sql-server

I have got a CTE with this sort of data
ID | Name | UserID | SupervisorID
1. Mark 1 2
2. John 1 1
3. Julia 3 1
4. Tomm 1 2
5. Eric 2 2
And if the SupervisorID is equal 2, then the rows with UserID equal 1 should NOT be returned.
If the SupervisorID is equal 1, then the rows with UserID equal 1 should NOT be returned.
I have tried with this query, but got stuck and can't figure out how to solve this problem.
SELECT * FROM CTE WHERE UserID <> CASE SupervisorID WHEN 1 THEN ??

Related

Multiplying Count of Instances in SQL

I have a data base that I need to query to count and sum the number of points generated by a pass from a player in a basketball game. For instance, if a player passes to a teammate and that pass results in 2 points, my data base currently stores that as 1 instance in certain table. There is another table that the data is stored in if the pass resulted in 3 points. I would like to query so that all instances of a pass from a player that results in 2 points are counted and then multiplied by 2, and all instances of a pass from a player that results in 3 points are counted and then multiplied by 3.
Here are my relevant tables and select statements:
CREATE TABLE Passer(
PasserID int identity PRIMARY KEY not null
, Forename char(30) not null
, Surname char (30) not null)
CREATE TABLE Teammate(
TeammateID int identity PRIMARY KEY not null
, Forename char(30) not null
, Surname char(30) not null
, PasserID int FOREIGN KEY REFERENCES Passer(PasserID) not null)
CREATE TABLE TwoPointsFromShot(
TwoPointsFromShotID int identity PRIMARY KEY not null
, PasserID int FOREIGN KEY REFERENCES Passer(PasserID) not null
, TeammateID int FOREIGN KEY REFERENCES Teammate(TeammateID) not null)
CREATE TABLE ThreePointsFromShot(
ThreePointsFromShotID int identity PRIMARY KEY not null
, PasserID int FOREIGN KEY REFERENCES Passer(PasserID) not null
, TeammateID int FOREIGN KEY REFERENCES Teammate(TeammateID) not null
--First and Last Name of Passer from TwoPointsFromShot--
SELECT Forename, Surname
FROM Passer
JOIN TwoPointsFromShot ON TwoPointsFromShot.PasserID = Passer.PasserID
--First And Last name of Passer from ThreePointsFromShot--
SELECT Forename, Surname
FROM Passer
JOIN ThreePointsFromShot ON ThreePointsFromShot.PasserID = Passer.PasserID
When I query the PasserID from the TwoPointsFromShot table, I receive a table that looks like:
| PasserID
------------------- | --------
1 | 1
2 | 3
3 | 3
4 | 2
I receive a similar table when querying PasserID from ThreePointsFromShot table.
| PasserID
--------------------- | --------
1 | 3
2 | 1
3 | 3
4 | 4
I would like to return a query that counts the number of instances of the PasserID from TwoPointsFromShot and multiplies that by 2, counts the number of instances of the PasserID from ThreePointsFromShot and multiples that by 3, sums the two values, and replaces the PasserID with the name of the player. So it would look like this (if Julius Randle is PlayerID 1, Dario Saric is PlayerID 2, TJ McConnell is PlayerID 3, and Brandon Ingram is PlayerID 4):
| PasserName | PointsFromTwo | PointsFromThree | PassToPoints
--- | --------- | --------------- | ------------------ | ------------
1 | Julius Randle | 2 | 3 | 5
2 | Dario Saric | 2 | 0 | 2
3 | TJ McConnell | 4 | 6 | 10
4 | Brandon Ingram| 0 | 3 | 3
Any help would be greatly appreciated!
I was able to get the results you want by using two common table expressions.
--CTE to get number of 2 pointers
WITH twoPointers AS
(
SELECT PasserId,COUNT(*) '2ptCount'
FROM TwoPointsFromShot
GROUP BY PasserID
),
--CTE to get number of 3 pointers
threePointers As
(
SELECT PasserId,COUNT(*) '3ptCount'
FROM ThreePointsFromShot
GROUP BY PasserID
)
--Join the Passer table with 2 CTE's and
--calculate results
SELECT RTRIM(Forename) + ' ' + RTRIM(Surname) AS 'PasserName',
ISNULL(two.[2ptCount] * 2, 0.00) AS 'PointsFromTwo',
ISNULL(three.[3ptCount] * 3, 0.00) AS 'PointsFromThree',
ISNULL(two.[2ptCount] * 2, 0.00) + ISNULL(three.[3ptCount] * 3, 0.00) AS 'PassToPoints'
FROM Passer p
LEFT JOIN twoPointers two ON p.PasserID = two.PasserID
LEFT JOIN threePointers three ON p.PasserID = three.PasserID

Flag missing record between 2 datasets

The Title doesn't quite explain the issue, so I will give an example:
Table 1 (OrderNum, OrderLine) - All OrderLines ever created.
Table 2 (OrderNum, OrderLin) - Order Lines to be printed right now.
Table 2 always has matches in Table 1 as it is populated from table 1, but sometimes is missing a Line from an order in Table 1. For instance:
Table 1:
OrderNum, OrderLine
100, 1
100, 2
100, 3
100, 4
101, 1
102, 1
102, 2
Table 2:
OrderNum, OrderLine
100, 1
100, 2
100, 4
101, 1
In this instance I need to print all 4 lines of Order 100, with Line 3 flagged as missing, and all of Order 101, but none of order 102. Obviously my tables are much larger than this, but this sums up my dilemma. I cannot control how either table is populated.
If I LEFT Join Table 2 to Table 1 on OrderNum and OrderLine, then i get OrderNum 102 as well and I don't want that. If I Join on OrderNum Only then I get dupes of Order 100 for every line in Table 2, how do i find the 1 record not-duped?
Hope that makes sense as to my issue. I have tried Googling, but the terms are so generic I get way to many irrelevant results.
using a left join and exists():
select
t1.OrderNum
, t1.OrderLine
, Missing = case when t2.OrderLine is null then 'Flag' else '' end
from t1
left join t2
on t1.OrderNum = t2.OrderNum
and t1.OrderLine = t2.OrderLine
where exists (
select 1
from t2 i
where t1.OrderNum = i.OrderNum
)
rextester demo: http://rextester.com/SZPX33524
returns:
+----------+-----------+---------+
| OrderNum | OrderLine | Missing |
+----------+-----------+---------+
| 100 | 1 | |
| 100 | 2 | |
| 100 | 3 | Flag |
| 100 | 4 | |
| 101 | 1 | |
+----------+-----------+---------+

Best Practice to Update EAV table rows

I have the following table:
SubjectID AttributeID ValueID
1 1 2
1 1 3
1 2 1
2 1 3
2 2 1
1 3 1
An attribute can have multiple values (multiple appearances in the above table for the same attribute).
There is no constraint of how many appearances for the same attribute (different value).
I wan't to Update the Subject with SubjectID=1, to change the ValueID to only 1 where the AttributeID is 1, so
Before:
Select * from Subject WHERE SubjectID=1 AND AttributeID=1
--returns:
SubjectID AttributeID ValueID
1 1 2
1 1 3
After:
Select * from Subject WHERE SubjectID=1 AND AttributeID=1
--returns:
SubjectID AttributeID ValueID
1 1 1
I am doing this with a stored procedure with optional parameters (all null and update only the attributes that were provided), now this is not an issue. My question is:
What is the best practice to update this rows? I see the following answers as viable:
Delete all the rows that contain the specified attribute, then insert the new ones;
If there is only one attribute of that type (for the specified subject) update that one (not a good solution if there are more than 1 for the same attribute)
Any other ideas?
You could update just one row and then delete the others like so:
set rowcount 1;
update Subject
set ValuedID = 1
where SubjectID = 1
and AttributeID = 1;
set rowcount 0;
delete Subject
where SubjectID = 1
and AttributeID = 1
and ValuedID <> 1;
Using set rowcount is deprecated, use top (n) instead.
Important
Using SET ROWCOUNT will not affect DELETE, INSERT, and UPDATE statements in a future release of SQL Server. Avoid using SET ROWCOUNT with DELETE, INSERT, and UPDATE statements in new development work, and plan to modify applications that currently use it. For a similar behavior, use the TOP syntax. For more information, see TOP (Transact-SQL).
update top (1) Subject
set ValueID = 1
where SubjectID = 1
and AttributeID = 1;
delete Subject
where SubjectID = 1
and AttributeID = 1
and ValueID <> 1;
rextester demo: http://rextester.com/ATDKI87027
returns:
+-----------+-------------+---------+
| SubjectID | AttributeID | ValueID |
+-----------+-------------+---------+
| 1 | 1 | 1 |
| 1 | 2 | 1 |
| 2 | 1 | 3 |
| 2 | 2 | 1 |
| 1 | 3 | 1 |
+-----------+-------------+---------+

Query that shows data depending of 2 columns

I'm working on a Report in Visual Basic. It has a query to show the information below.
So, I need a query that sets all the rows that are between 2 values that the user choose. The problem is that the value exists several times.
To explain better:
ID Category_ID SubCategory_ID Description Period_ID Data
----------- ----------- -------------- ------------- ----------- --------
1 1 1 PRUEBA 1 100.00
2 2 5 Total 1 2.00
3 1 1 sgsdg 2 25.00
4 1 1 fsdf 2 5.00
5 1 1 sdf 2 54.00
There will be a lot more of Period_ID. So, if the user chooses Period 1 and Period 5, it will show all the data between Period 1 and Period 5 (i.e. Period1, Period2, Period3, Period4 and Period5).
Is there a query which can do this?
I appreciate your help!
I would do:
Select *
FROM SAMPLE_TABLE
WHERE SAMPLE_TABLE.PERIOD_ID
IN (SELECT ID FROM PERIOD
WHERE ID >= 1 AND ID <= 5)
This is called a subquery. This relies on you have a period table, which I assume you have

How to do recursive select in PostgreSQL with array as an argument

I am trying to implement easy recursive function in PostgreSQL but I cannot finish it...
I have got table MyTable which includes columns Col1 and Col2. Data inside is like this:
Col1 | Col2
1 | 2
2 | 5
2 | 6
3 | 7
4 | 5
4 | 2
5 | 3
I would like to write a function which takes as a parameter array of Col1 f.e. (1,2) and gives me back values from Col2 like this :
1 | 2
2 | 5
2 | 6
and after that, does it again with results : (2, 5, 6)
so:
1 | 2
2 | 5
2 | 6
5 | 3
(2 is already in, and key '6' does not exist)
and again (3):
1 | 2
2 | 5
2 | 6
5 | 3
3 | 7
and for (7) nothing because value '7' does not exist in Col1.
It is an easy recursion but I have no idea how to implement it. I have got so far something like this:
with recursive aaa(params) as (
select Col1, Col2
from MyTable
where Col1 = params -- I need an array here
union all
select Col1, Col2
from aaa
)
select * from aaa;
But it of course does not work
Thanks in advance
The basic pattern for recursion is to have your base case as the first part of the union and in the second part join the recursion result to what you need to produce the next level of results. In your case it would look like this:
WITH RECURSIVE aaa(col1, col2) AS (
SELECT col1, col2 FROM mytable
WHERE col1 = ANY (ARRAY[1,2]) -- initial case based on an array
UNION -- regular union because we only want new values
SELECT child.col1, child.col2
FROM aaa, mytable AS child -- join the source table to the result
WHERE aaa.col2 = child.col1 -- the recursion condition
)
SELECT * FROM aaa;

Resources