SQL Query inner joins - sql

I am working on SQL Server 2008 R2.
I have two tables let us say TblGroup and TblComplatedDetails.
TblGroup contains the name of Groups along with MemberId and GroupType (i.e. in Daily, Weekly, Start, End) and TblComplatedDetails contains GroupId (i.e. foreign key of TblGroup) along with completed datetime.
Now I want all the group of specific MemberId except GroupType="End" AND "Start" type of Group only if it has no record in TblCompletedDetails. So the record set is something like below :
TblGroup
==================================
Id MemberId GroupType
==================================
1 1 Daily
2 2 Daily
3 3 Daily
4 1 Weekly
5 1 Start
6 2 Weekly
7 2 Start
8 2 End
9 1 End
10 1 End
TblCompletedDetails
======================================
Id GroupId CompletedDate
======================================
1 1 xxxxxxxxxxxxxx
2 2 xxxxxxxxxxxxxx
3 3 xxxxxxxxxxxxxx
4 4 xxxxxxxxxxxxxx
5 1 xxxxxxxxxxxxxx
6 2 xxxxxxxxxxxxxx
7 3 xxxxxxxxxxxxxx
8 5 xxxxxxxxxxxxxx
9 6 xxxxxxxxxxxxxx
So for MemberId = 1 the desired Groups can be :
=======
GroupId
=======
1
4
But for MemberId = 2 the desired resule is :
=======
GroupId
=======
2
6
7
Because 7 is a "Start" type of Group that has not foreign key in TblCompletedDetails.
Can anyone have idea? Awaiting for your valuable response.

select g.ID GroupID
from TblGroup g
where g.MemberID = #MemberID
and g.GroupType <> 'end'
and
(
-- Row is qualified if it is not start
g.GroupType <> 'start'
-- Or, if it is, does not have an entry in TblCompletedDetails
or not exists (select *
from TblCompletedDetails d
where d.GroupId = g.ID)
)

Related

How to join two tables - Get a count - As well as show max date

sorry I have no clue on how to do this.
Here is some sample data.
Data Data Entry
Name Active key Name Active Date key
Name 1 1 1 Name 1 1 Jan-15 1
Name 2 0 2 Name 2 1 Feb-15 2
Name 3 1 3 Name 1 1 Jan-14 1
Name 4 1 4 Name 3 1 Feb-15 3
Name 5 1 5 Name 3 0 Jan-14 3
Name 6 0 6 Name 4 1 Feb-15 4
Name 7 1 7 Name 5 1 Mar-15 5
Name 8 1 8 Name 6 1 Apr-15 6
Two tables Data , and Data_Entry you can say.
How do I get an output from this where it shows.
data.active = '1' and data_entry.active = '1' for each key ? as well as the count that it shows up in the data_entry
I would want the output to be for example this : As it is only showing me active data that has an active entry in the data_entry table and the count to be only that of active entries from data_entry
name last_date count
name 1 Jan-15 2
name 3 Feb-15 1
name 4 Feb-15 1
Name 5 Mar-15 1
Name 6 Apr-15 1
I think that should work for you:
SELECT
name,
MAX(date) AS last_date,
COUNT(*) AS count
FROM (
SELECT
data.key
data.name,
data_entry.key,
data_entry.date
FROM data
INNER JOIN data_entry ON data_entry.key = data.key
WHERE data.active = 1 AND data_entry.active = 1
) subquery
GROUP BY key, name

Multiply newly entered row with another column value and find Total Sum in SQL

I have 4 tables here, I need to multiply newly entered row value in a table with another row and find the total sum using CustomerId:
CustomerTable:
CustomerId Name EmailId
-------------------------
1 Paul r#r.com
2 John J#j.com
LoyaltyPointTable:
LoyaltyPointsId LoyaltyType Points
---------------------------------------
1 Registration 10
2 Loginstatus 1
3 Downloading 10
4 Redemming 1
5 Sharing 20
6 Refer 10
LoyaltyDetailsTable:
LoyaltyDetailsId LoyaltyPointsId CustomerId Dates
-------------------------------------------------
1 1 1 2015-01-22
2 2 1 2015-01-22
3 3 2 2015-01-22
4 3 1 2015-01-22
5 4 1 2015-01-22
6 4 1 2015-01-24
7 5 1 2015-01-24
This query works fine for the total sum for each LoyaltyType
SELECT
LoayaltyPointsTable.LoyaltyType,
COUNT(CustomerTable.CustomerId) AS UserActions,
SUM(LoayaltyPointsTable.Points) AS TotalPoints
FROM
LoayaltyPointsTable
JOIN
LoyaltyDetailsTable ON LoayaltyPointsTable.LoyaltyPointsId = LoyaltyDetailsTable.LoyaltyPointsId
JOIN
CustomerTable ON CustomerTable.CustomerId = LoyaltyDetailsTable.CustomerId
WHERE
CustomerTable.CustomerId = 1
GROUP BY
LoyaltyDetailsTable.CustomerId ,LoayaltyPointsTable.LoyaltyType
below RedeemPointsTable is created with relation to row redeeming in LoyaltyPointTable:
RedeemPointsTable:
RedeemPointsId CustomerId ShopName BillNo Amount
------------------------------------------------
1 1 Mall x 4757 100
3 1 Mall y SH43 50
4 1 Mall x 7743 10
6 1 Mall x s34a 60
What I am expecting is before calculating the total sum, I want column Amount sum (100+50+10+60) * 1 in Redeeming in LoyaltyPointTable to be added with total points for each CustomerId
Expected output
LoyaltyType UserActions TotalPoints
-------------------------------------
Downloading 1 10
Loginstatus 1 1
Redemming 4 (100+50+10+60)*1(here using Amount in RedeemPointsTable)
Refer 1 10
Registration 1 10
Sharing 1 20
User actions count is 4, it is based on the Amount he entered in RedeemPointsTable
Should I need to make changes in adding a foreign key column in RedeemPointsTable or can you point out my mistake?
Any help would be great.
This is the query which returns desired result:
SELECT
LoyaltyPointTable.LoyaltyType,
CASE
WHEN LoyaltyPointTable.LoyaltyPointsId=4 THEN (SELECT COUNT(amount) FROM RedeemPointsTable where CustomerId=1)
ELSE COUNT(CustomerTable.CustomerId)
END as UserActions,
CASE
WHEN LoyaltyPointTable.LoyaltyPointsId=4 THEN (SELECT SUM(amount) FROM RedeemPointsTable where CustomerId=1)*Points
ELSE SUM(LoyaltyPointTable.Points)
END as TotalPoints
FROM
LoyaltyPointTable
JOIN
LoyaltyDetailsTable ON LoyaltyPointTable.LoyaltyPointsId = LoyaltyDetailsTable.LoyaltyPointsId
JOIN
CustomerTable ON CustomerTable.CustomerId = LoyaltyDetailsTable.CustomerId
WHERE
CustomerTable.CustomerId = 1
GROUP BY
LoyaltyDetailsTable.CustomerId ,LoyaltyPointTable.LoyaltyType
You can check it here

Selecting rows and filler (null data)

I have a table that looks like this:
ReportID | TeamID | Inning | Runs
1 A 1 3
1 A 2 3
1 A 5 7
1 B 1 3
1 B 3 2
1 B 6 1
I need to select all of that data, plus null data for the missing innings. It also need to stop at the max Inning for both teams (i.e. teamB's highest inning is 6, so I would collect 6 rows for both teamA and teamB yielding 12 total rows.)
For a visual, I need the output of the query to look like this:
ReportID | TeamID | Inning | Runs
1 A 1 3
1 A 2 3
1 A 3 NULL
1 A 4 NULL
1 A 5 7
1 A 6 NULL
1 B 1 3
1 B 2 NULL
1 B 3 2
1 B 4 NULL
1 B 5 NULL
1 B 6 1
Is there anyway to do this with just a query? Modifying the original table to add the null values is not an option.
Self join to generate the permutations of reports and teams
Left self join to generate hits which might be nullable.
This is probably a lot more efficient if it's done outside of SQL
SELECT ins.ReportID, teams.TeamID, ins.inning, score.Runs
FROM games as ins
JOIN games AS teams
ON ins.ReportID = teams.ReportID
LEFT JOIN games AS score
ON ins.ReportID = score.ReportID
AND teams.TeamID = score.TeamID
AND ins.inning = score.inning
GROUP BY ins.ReportID, teams.TeamID, ins.inning;

How to apply Joins in Oracle to require result

I have Following 3 tables :
SHIFT_MASTER,PATTERN_MASTER,PATTERN_DETAILS
S_ID ,P_ID,P_D_ID are the priamry keys of SHIFT_MASTER,PATTERN_MASTER,PATTERN_DETAILS tables respectively.
SHIFT_MASTER
S_ID | S_NUMBER| S_Name
---------------------------------
1 A MORNING
2 B AFTERNOON
3 C NIGHT
PATTERN_MASTER
P_ID | P_NAME
----------------
1 Pattern 1
2 Pattern 2
PATTERN_DETAILS
P_D_ID|P_ID | S_ID| ...
---------------------
1 1 1
2 1 2
3 1 3
4 1 2
5 1 1
6 2 3
7 2 2
8 2 1
9 2 3
I GOT OUTPUT AS
P_ID | S_ID
1 1,2,3,2,1
2 3,2,1,3
USING QUERY
SELECT PATTERN_DETAILS.P_ID "PATTERN",
LISTAGG(PATTERN_DETAILS.S_ID, ', ')
WITHIN GROUP (ORDER BY PATTERN_DETAILS.P_D_ID) "SHIFT"
FROM PATTERN_DETAILS
GROUP BY PATTERN_DETAILS.P_ID;
WHAT I WANT IS
P_NAME | S_NUMBER
Pattern 1 A,B,C,B,A
Pattern 2 C,B,A,C
Any suggestion ??? Instead of P_ID i want to show pattern name and instead of shift id i want to show shift number .How to perform join operation along with listagg function ?
You need to join all three tables to get this,
SELECT pm.p_name "P_NAME",
listagg(sm.s_number, ', ') WITHIN GROUP (ORDER BY pd.p_d_id) "S_NUMBER"
FROM pattern_master pm,
pattern_details pd,
shift_master sm
WHERE sm.s_id= pd.s_id
AND pm.p_id = pd.p_id
GROUP BY pm.p_name;

Matching two variables to create a new ID

I'm trying to create an SQL statement to match either an id number or a postcode and then assign a new id number
What I want to end up with is ‘newid’ that correctly recognizes that the first four records are the same person (even though the postcode for record 2 is different).
record id postcode newid
--------------------------
1 1 1 1
2 1 2 1
3 1 1 1
4 2 1 1
5 3 3 2
Any suggestions would be appreciated greatly.
Going based on your example:
SELECT RECORD,
(SELECT MIN (ID)
FROM users u2
WHERE users.id IN (u2.id, u2.postcode)
OR users.postcode in (u2.id, u2.postcode)
) AS newid
FROM users
This results with the following data:
RECORD NEWID
------------------
1 1
2 1
3 1
4 1
5 3
Here is the SQLFiddle