Query multilayer table in sql - sql

I am trying to retrieve the UserInfo with the UserId=10004 with all his friends and all the posts of his friends and all the likes on those posts. And for that I am using a query :
select *,
(select * ,
(select * ,
(select * from PostLikes where PostId=UserPosts.PostId) as likes
from UserPosts where UserId=FriendsRelation.PersonId1 or UserId=FriendsRelation.PersonId2) as posts
from FriendsRelation where PersonId1=UserId or PersonId2=UserId) as friends
from UserInfo
where UserId=10004
but it is returning with an error
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS
How can I solve it?
Here are the tables that I am using:
CREATE TABLE [dbo].[UserInfo]
(
[UserId] [bigint] IDENTITY(1,1) NOT NULL,
[Username] [nvarchar](max) NULL,
[Email] [nvarchar](max) NOT NULL,
[UserPassword] [nvarchar](max) NOT NULL,
[Name] [nvarchar](max) NULL,
[Gender] [nchar](10) NOT NULL,
[ContactNo] [bigint] NOT NULL,
[DateOfBirth] [date] NOT NULL,
[RelationshipStatus] [nchar](10) NULL,
[InterestedIn] [nchar](10) NULL,
[Address] [nvarchar](max) NULL,
[Country] [nchar](10) NOT NULL,
[FavouriteQuote] [nvarchar](max) NULL,
[DisplayPhoto] [nvarchar](max) NULL,
[Guid] [nvarchar](max) NOT NULL,
[Status] [tinyint] NOT NULL CONSTRAINT [DF_UserInfo_Status] DEFAULT ((1)),
[CreatedDate] [datetime] NOT NULL,
[LastLogIn] [datetime] NULL,
CONSTRAINT [PK_UserInfo]
PRIMARY KEY CLUSTERED ([UserId] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
UserPosts table:
CREATE TABLE [dbo].[UserPosts]
(
[PostId] [bigint] IDENTITY(1,1) NOT NULL,
[UserId] [bigint] NOT NULL,
[PostText] [nvarchar](max) NULL,
[PostPicture] [nvarchar](max) NULL,
[Time] [time](7) NOT NULL,
[Date] [date] NOT NULL,
[LikeCount] [int] NULL CONSTRAINT [DF_UserPosts_LikeCount] DEFAULT ((0)),
CONSTRAINT [PK_UserPosts]
PRIMARY KEY CLUSTERED ([PostId] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[UserPosts] WITH CHECK
ADD CONSTRAINT [FK_UserPosts_UserInfo]
FOREIGN KEY([UserId]) REFERENCES [dbo].[UserInfo] ([UserId])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[UserPosts] CHECK CONSTRAINT [FK_UserPosts_UserInfo]
GO
and PostLikes table:
CREATE TABLE [dbo].[PostLikes]
(
[LikeId] [bigint] IDENTITY(1,1) NOT NULL,
[PostId] [bigint] NOT NULL,
[UserId] [bigint] NOT NULL,
CONSTRAINT [PK_PostLike]
PRIMARY KEY CLUSTERED ([PostId] ASC, [UserId] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[PostLikes] WITH CHECK
ADD CONSTRAINT [FK_PostLikes_UserInfo]
FOREIGN KEY([UserId]) REFERENCES [dbo].[UserInfo] ([UserId])
GO
ALTER TABLE [dbo].[PostLikes] CHECK CONSTRAINT [FK_PostLikes_UserInfo]
GO
ALTER TABLE [dbo].[PostLikes] WITH CHECK
ADD CONSTRAINT [FK_PostLikes_UserPosts]
FOREIGN KEY([PostId]) REFERENCES [dbo].[UserPosts] ([PostId])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[PostLikes] CHECK CONSTRAINT [FK_PostLikes_UserPosts]
GO

Similar to other people's answers, but use left joins for everything (in case the user has no friends), and some changes to join logic.
declare #userID int = 10004 --For easy swapping out if you want to query someone else
Select * from UserInfo a
left join FriendsRelation b
on b.PersonID1 = #userID or b.PersonID2 = #userID --Faster than joining and then filtering, if you're only looking for one person at a time
left join UserPosts c
on (c.UserID = b.PersonID1 or c.UserID = b.PersonID2)
and c.UserID <> #userID --returns only friends' posts, not user's posts, as specified in original question
left join postLikes d
on d.PostID = c.PostID
where a.UserID = #userID

You can use JOINS like this:
select *
from UserInfo
inner join FriendsRelation on UserInfo.UserId = FriendsRelation.PersonId1 or UserInfo.UserId = FriendsRelation.PersonId2
inner join UserPosts on FriendsRelation.PersonId1 = UserPosts.UserId
inner join PostLikes on UserPosts.PostId = PostLikes.PostId
where UserInfo.UserId=10004

As already mentioned, you need to use join instead of subqueries. Probably this query will be useful for you
select *
from UserInfo
inner join FriendsRelation
on UserInfo.UserId = FriendsRelation.PersonId1
inner join UserPosts
on FriendsRelation.PersonId1 = UserPosts.UserId
left outer join PostLikes
on UserPosts.PostId = PostLikes.PostId
where UserInfo.UserId=10004
union
select *
from UserInfo
inner join FriendsRelation
on UserInfo.UserId = FriendsRelation.PersonId2
inner join UserPosts
on FriendsRelation.PersonId2 = UserPosts.UserId
left outer join PostLikes
on UserPosts.PostId = PostLikes.PostId
where UserInfo.UserId=10004

Related

Sql server database store procedure query

I have two tables as below:
1) UserFavouriteCurrencies
CREATE TABLE [dbo].[UserFavouriteCurrencies](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[UserId] [int] NULL,
[CurrencyId] [int] NULL,
[EntryDate] [datetime] NULL,
CONSTRAINT [PK_UserFavouriteCurrencies] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
Above table is holding data of user favorite companies
2) CurrencyRates
CREATE TABLE [dbo].[CurrencyRates](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[CurrencyId] [int] NULL,
[Price] [float] NULL,
[Open_24h] [float] NULL,
[Volume_24h] [float] NULL,
[Low_24h] [float] NULL,
[High_24h] [float] NULL,
[Volume_30d] [float] NULL,
[BestBid] [float] NULL,
[BestAsk] [float] NULL,
[TradeId] [bigint] NULL,
[PriceDate] [datetime] NULL,
[PriceDateTimestamp] [bigint] NULL,
[OpenInterest] [float] NULL,
CONSTRAINT [PK_CoinbaseTickerRatesMaster] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
Above table holds rates details of currencies.
Call : EXEC sp_Getdata 1(Here 1 in UserId of UserFavouriteCurrencies table)
I need all records for particular currencies last latest records in one query as below
DECLARE #Today DATETIME = GETDATE(), #PrevDate DATETIME = GETDATE()<br>
SELECT TOP 1 Price, PriceDate, Volume_24h, PriceDateTimestamp
FROM CurrencyRates
WHERE CurrencyId = #CurrencyId AND PriceDate <= #Today
ORDER BY PriceDateTimestamp DESC
Above query is only select data for one particular currency but I need the data related to user which added on UserFavouriteCurrencies table.
Please help me to write store procedure for this query
Thanks in advance.
For each currency in UserFavouriteCurrencies Table, consider the query below
SELECT
uc.Id -- This is the userId
,cr.Price
,cr.PriceDate,
,cr.Volume_24h
,cr.PriceDateTimestamp
FROM
UserFavouriteCurrencies AS uc
INNER JOIN CurrencyRates AS cr -- See Hints : 1
ON cr.CurrencyId = uc.CurrencyId
WHERE
PriceDate <= GETDATE()
AND
uc.Id = #Id
-- You can add other Predicates Here...
Hints:
Consider using LEFT OUTER JOIN if user's currency may not exist in CurrencyRates
!This will however introduce NULLs which you must handle

Why is my simple SQL statement taking so long to execute and how do i go about finding the issue?

I have a very simple SQL query:
select o.Visit_ID
from Datamart.dbo.ww_Orders o
inner join Datamart.dbo.ww_Order_Details on o.Visit_ID = ww_Order_Details.Visit_ID
where o.runstamp = '20160422'
this query takes < 0 seconds to return 11173 rows
When I add the GROUP BY statement:
select o.Visit_ID
from Datamart.dbo.ww_Orders o
inner join Datamart.dbo.ww_Order_Details on o.Visit_ID = ww_Order_Details.Visit_ID
where o.runstamp = '20160422'
group by o.Visit_ID
the server takes 6min 30 sec to retrieve the 3047 rows.
I would expect the GROUP BY query to take not that much longer than the original. How do I go about finding what the issues are? thanks
here are the table definitions:
Orders:
CREATE TABLE [dbo].[ww_Orders](
[Visit_ID] [int] NOT NULL,
[Member_ID] [int] NOT NULL,
[Membership_no] [varchar](20) NULL,
[Member_Card_Num_Orig] [varchar](16) NULL,
[SCV_ID] [int] NULL,
[Meeting_No] [int] NULL,
[Location_Name] [varchar](128) NULL,
[Leader_No] [int] NULL,
[CashAmt] [decimal](18, 2) NULL,
[EFTAmt] [decimal](18, 2) NULL,
[VouchAmt] [decimal](18, 2) NULL,
[Meet_Date] [datetime] NULL,
[runstamp] [varchar](50) NULL,
CONSTRAINT [PK_dbo.ww_Orders] PRIMARY KEY CLUSTERED
(
[Visit_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
Order Details:
CREATE TABLE [dbo].[ww_Order_Details](
[ord_det_pk] [int] IDENTITY(1,1) NOT NULL,
[Visit_ID] [int] NOT NULL,
[Item_Code] [nvarchar](50) NULL,
[Item_Name] [nvarchar](50) NULL,
[Qty] [int] NULL,
[Amt] [decimal](18, 2) NULL,
[Category_Code] [nvarchar](20) NULL,
CONSTRAINT [PK_ww_Order_Details] PRIMARY KEY CLUSTERED
(
[ord_det_pk] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[ww_Order_Details] WITH CHECK ADD CONSTRAINT [FK_ww_Order_Details_ww_Orders] FOREIGN KEY([Visit_ID])
REFERENCES [dbo].[ww_Orders] ([Visit_ID])
GO
ALTER TABLE [dbo].[ww_Order_Details] CHECK CONSTRAINT [FK_ww_Order_Details_ww_Orders]
GO
I'd add an index onto ww_Order_Details Visit_ID, probably make it the clustered index and drop the index on ord_det_pk. Also it might make more sense as an exists?
select o.Visit_ID
from Datamart.dbo.ww_Orders o
where exists (select 0 from Datamart.dbo.ww_Order_Details where o.Visit_ID = ww_Order_Details.Visit_ID)
and o.runstamp = '20160422'
I usually try to use a common table expression in cases like these, when a part of the query is really fast but an addition of a simple operation makes it really slow, usually it helps.
Try:
WITH CTE AS (
select o.Visit_ID
from Datamart.dbo.ww_Orders o
inner join Datamart.dbo.ww_Order_Details od on o.Visit_ID = od.Visit_ID
where o.runstamp = '20160422'
)
SELECT Visit_ID FROM CTE
group by Visit_ID
If this helps you can try to compare execution plans for your original query and this version to see whats going on

SQL Descending ordered LEFT JOIN subquery issue

I have the following query.
SELECT r1.*,
r2.vlag54,
r2.vlag55
FROM [rxmon].[dbo].[a] AS r1
LEFT JOIN [rxmon].[dbo].[b] AS r2
ON r2.artikelnummer = r1.drug_id
LEFT JOIN (SELECT *
FROM [rxmon].[dbo].[c]) AS r3
ON r3.pid = r1.patient_id
WHERE r3.obx_id = 20937
AND Cast(r3.obx_datetime AS DATE) = Cast(Getdate() - 1 AS DATE)
AND r1.patient_id = 7092425
AND obx_value < CASE
WHEN r2.vlag54 = 1 THEN 30
WHEN r2.vlag55 = 1 THEN 50
END
AND r2.vlag54 = CASE
WHEN r3.obx_value < 30 THEN 1
ELSE 0
END
AND r2.vlag55 = CASE
WHEN r3.obx_value BETWEEN 30 AND 50 THEN 1
ELSE 0
END
ORDER BY obx_datetime DESC;
The problem is that table C can contain multiple records based on de PID join. This generates the same records because of the multiple records on table C.
The table C needs to e joined as the latest record only so just 1 of C. That way the table A record will not be repeated.
I tried TOP 1 and order by but that can't be used in subquery.
-- TABLE A
CREATE TABLE [dbo].[A]
[EVS_MO_ID] [bigint] NOT NULL,
[DRUG_ID] [varchar](50) NOT NULL,
[ATC_CODE] [varchar](15) NULL,
[DRUG_NAME] [varchar](1024) NULL,
[PATIENT_ID] [varchar](50) NOT NULL,
[PATIENT_LOCATION] [varchar](10) NULL,
[MO_DATE] [datetime2](7) NOT NULL,
[MO_START_DATE] [datetime2](7) NOT NULL,
[MO_STOP_DATE] [datetime2](7) NULL,
[ROUTE] [varchar](50) NULL,
[MEDICATION_CONTAINER] [smallint] NULL,
[PRESCRIBING_DOCTOR_NAME] [varchar](50) NULL,
[PRESCRIBING_DOCTOR_SURNAME] [varchar](50) NULL,
[MO_ACTIVE] [bit] NOT NULL,
CONSTRAINT [PK_MedicationOrders] PRIMARY KEY CLUSTERED
(
[EVS_MO_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = ON, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
INSERT INTO [dbo].[A]
VALUES
(5411409,'97941689', 'B01AB06','NADROPARINE 0.8ML','7092425','ANBC', '2015-12-15 20:58:06.2030000',
'2015-12-16 00:00:00.0000000', '', 'IV', 1, 'GEORGE','LAST', 1);
-- TABLE B
CREATE TABLE [dbo].[B](
[ID] [int] IDENTITY(1,1) NOT NULL,
[ARTIKELNUMMER] [varchar](50) NOT NULL,
[VLAG54] [bit] NULL,
[VLAG55] [bit] NULL CONSTRAINT [DF_Table_1_VLAG50] DEFAULT ((0)),
[VLAG100] [bit] NULL CONSTRAINT [DF_ArtikelVlaggen_VLAG100] DEFAULT ((0)),
CONSTRAINT [PK_B] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
INSERT INTO [dbo].[B]
([ARTIKELNUMMER]
,[VLAG54]
,[VLAG55]
,[VLAG100])
VALUES
('97941689', 1,0,1);
-- TABLE C
CREATE TABLE [dbo].[C](
[ID] [int] IDENTITY(1,1) NOT NULL,
[OBX_DATETIME] [datetime2](7) NOT NULL,
[PID] [int] NOT NULL,
[DEPARTMENT] [varchar](8) NOT NULL,
[OBX_ID] [int] NOT NULL,
[OBX_VALUE] [decimal](5, 2) NOT NULL,
[OBX_UNITS] [varchar](10) NULL,
[REF_RANGE] [varchar](40) NULL,
[FLAG] [varchar](2) NULL,
CONSTRAINT [PK_C] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
INSERT INTO [dbo].[C]
([OBX_DATETIME]
,[PID]
,[DEPARTMENT]
,[OBX_ID]
,[OBX_VALUE]
,[OBX_UNITS]
,[REF_RANGE]
,[FLAG])
VALUES
('2015-12-15 14:01:00.0000000',7092425, '8NAH', 20937, 27.00, 'mL/min', '> 60', 'L');
INSERT INTO [dbo].[C]
([OBX_DATETIME]
,[PID]
,[DEPARTMENT]
,[OBX_ID]
,[OBX_VALUE]
,[OBX_UNITS]
,[REF_RANGE]
,[FLAG])
VALUES
('2015-12-15 06:30:00.0000000',7092425, '6ZPA', 20937, 28.00, 'mL/min', '> 60', 'L');
This will order them by OBX_DATETIME and take only the first one:
...
LEFT JOIN (
SELECT pid, obx_id, obx_datetime, obx_value
, n = ROW_NUMBER() over(PARTITION BY pid ORDER BY obx_datetime desc)
FROM [rxmon].[dbo].[c]
) AS r3
ON r3.pid = r1.patient_id and r3.n = 1
...
If OBX_DATETIME are inserted incrementaly (newer date only), you can order by ID instead.
This SQL Fiddle with your query and sample data/tables returns 2 rows: http://sqlfiddle.com/#!3/df36c/2/0
This SQL Fiddle with the new subquery returns 1 row: http://sqlfiddle.com/#!3/df36c/1/0
You are using a LEFT JOIN on r3 but have also have r3 in your WHERE clause with equal operator:
WHERE r3.obx_id = 20937
AND Cast(r3.obx_datetime AS DATE) = Cast(Getdate() - 1 AS DATE)
It will remove NULL value from the left join on r3. Perhaps you should also move it to the sub query or use INNER JOIN.
You should also avoind using the DB name in your query unless this query is run from another DB on the same server. This will be fine:
SELECT ... FROM [dbo].[a] AS r1 ...
Using SELECT * is also a bad habit. You should list only the columns your code will use.
try this.... #Shift
SELECT r1.*,
r2.vlag54,
r2.vlag55
FROM [dbo].[a] AS r1
LEFT JOIN [dbo].[b] AS r2
ON r2.artikelnummer = r1.drug_id
LEFT JOIN (
SELECT
ROW_NUMBER() OVER (PARTITION BY pid ORDER BY id DESC) RN,
c.*
FROM C
) r3
ON r3.pid = r1.patient_id AND r3.RN = 1
WHERE r3.obx_id = 20937
AND Cast(r3.obx_datetime AS DATE) = Cast(Getdate() - 1 AS DATE)
AND r1.patient_id = 7092425
AND obx_value < CASE
WHEN r2.vlag54 = 1 THEN 30
WHEN r2.vlag55 = 1 THEN 50
END
AND r2.vlag54 = CASE
WHEN r3.obx_value < 30 THEN 1
ELSE 0
END
AND r2.vlag55 = CASE
WHEN r3.obx_value BETWEEN 30 AND 50 THEN 1
ELSE 0
END
ORDER BY obx_datetime DESC;

Figure Out Which OrderIDs are 0$ Payment Totals

I am in need to some help writing a SQL 2012 query that will help me find and mark orderID's that are a $0.00 payments due to reversal(s)
So far I have:
Select Distinct a.orderID, a.orderPaid,
(Select SUM((c1.linePrice + c1.lineShippingCost + c1.lineTaxCost + c1.lineOptionCost) * c1.lineQuantity)
From vwSelectOrderLineItems c1 Where c1.orderID = a.orderID) As OrderAmount,
(Select SUM(b1.payAmount) FROM vwSelectOrderPayments b1 Where b1.orderID = a.orderID) as Payment,
1 As IsReversal
From vwSelectOrders a
Left Outer Join vwSelectOrderPayments b On b.orderID = a.orderID
Where b.payValid = 1 AND a.orderPaid = 0
Which is returning me some $0 payments on some orders. When I query that payment table with the orderID of these records, I can see that 2 payments were posted... 1 the original payment, 2 the reversal.
How Can I flag the Orders that are $0 payments?
Oders
CREATE TABLE [dbo].[TblOrders](
[orderID] [bigint] IDENTITY(1000,1) NOT NULL,
[orderPaid] [bit] NOT NULL,
[orderPaidOn] [datetime] NULL
CONSTRAINT [PK_TblOrders] PRIMARY KEY CLUSTERED
(
[orderID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 50) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[TblOrders] ADD CONSTRAINT [DF__TblOrders__order__1975C517] DEFAULT ((0)) FOR [orderPaid]
Order Line Items
CREATE TABLE [dbo].[TblOrderLineItems](
[lineID] [bigint] IDENTITY(1,1) NOT NULL,
[orderID] [bigint] NOT NULL,
[lineQuantity] [int] NOT NULL,
[linePrice] [money] NOT NULL,
[lineShippingCost] [money] NOT NULL,
[lineTaxCost] [money] NOT NULL,
[lineOptionCost] [money] NOT NULL,
CONSTRAINT [PK_TblOrderLineItems] PRIMARY KEY CLUSTERED
(
[lineID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 50) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[TblOrderLineItems] ADD CONSTRAINT [DF_TblOrderLineItems_lineShippingCost] DEFAULT ((0)) FOR [lineShippingCost]
GO
ALTER TABLE [dbo].[TblOrderLineItems] ADD CONSTRAINT [DF_TblOrderLineItems_lineTaxCost] DEFAULT ((0)) FOR [lineTaxCost]
GO
ALTER TABLE [dbo].[TblOrderLineItems] ADD CONSTRAINT [DF_TblOrderLineItems_lineOptionCost] DEFAULT ((0)) FOR [lineOptionCost]
GO
Order Payments
CREATE TABLE [dbo].[TblOrderPayments](
[paymentID] [bigint] IDENTITY(1,1) NOT NULL,
[orderID] [bigint] NOT NULL,
[payAmount] [money] NOT NULL,
[payPosted] [datetime] NOT NULL,
[payValid] [bit] NOT NULL,
CONSTRAINT [PK_TblOrderPayments] PRIMARY KEY CLUSTERED
(
[paymentID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 50) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[TblOrderPayments] ADD CONSTRAINT [DF_TblOrderPayments_payValid] DEFAULT ((0)) FOR [payValid]
GO
Views
CREATE VIEW [dbo].[vwSelectOrderLineItems] AS
SELECT linePrice, lineShippingCost, lineTaxCost, lineOptionCost, lineQuantity
FROM [dbo].[TblOrderLineItems]
CREATE VIEW [dbo].[vwSelectOrderPayments] AS
SELECT paymentID, orderID, payAmount, payValid
FROM dbo.TblOrderPayments
CREATE VIEW [dbo].[vwSelectOrders] AS
SELECT orderID , orderPaid
FROM dbo.TblOrders
Note
I cannot change the table structure
SELECT distinct a.orderid,
a.orderPaid,
c.OrderAmount
d.Payment
From vwSelectOrders AS a
INNER JOIN ( Select SUM((linePrice + lineShippingCost + lineTaxCost + lineOptionCost) * lineQuantity) As orderAmount,OrderID
From vwSelectOrderLineItems group by orderid) AS C on c.orderID = a.orderID
INNER JOIN (Select SUM(payAmount) as Payment,orderID FROM vwSelectOrderPayments WHERE isnull(SUM(PayAmount),0) > 0 GROUP BY OrderID) AS d ON d.orderID = a.orderID
Left Outer Join vwSelectOrderPayments b On b.orderID = a.orderID
Where b.payValid = 1 AND a.orderPaid = 0 AND
This is a better query as you do not have to us a correlated subquery. Correlated queries are when a subquery references an outerquery row. This isn't optimal because every row the outerquery runs the correlated subquery will execute. Once you give us table definitions we can probably fix the overall data return of your query.

In a SQL Query, How do I do a join only on specific conditions?

I have the following SQL Query:
select Subjects.S_ID as ID,
Subjects.S_ParentID as ParentID,
Subjects.S_Name as Name,
Subjects.S_Order as [Order],
subjects.Sbj_IsVisible
from Subjects
left join KPI_SubjectDetails k on Subjects.S_ID = k.S_ID
where
subjects.Sbj_CourseID = 7594
and subjects.Sbj_Type=2
and subjects.Sbj_IsVisible=1
order by subjects.S_Level,
k.SD_Order
Each Subject has a s_ParentID. The most top subjects have a s_ParnetID of 0.
I want to add a SQL Join, which will do the following:
If a parent Subject is set to Sbj_IsVisible = 0 (any subject can be a parent), then the SQL should not output it or any of its children. However, if s_ParentID is set to 0, I don't want to do the Sbj_IsVisible check as this is the top most subject.
Here's what I got:
select Subjects.S_ID as ID,
Subjects.S_ParentID as ParentID,
Subjects.S_Name as Name,
Subjects.S_Order as [Order],
subjects.Sbj_IsVisible
from Subjects
join Subjects_tbl st on Subjects.S_ParentID = st.S_ID and subjects.S_ParentID <> 0
left join KPI_SubjectDetails k on Subjects.S_ID = k.S_ID
where
subjects.Sbj_CourseID = 7594
and subjects.Sbj_Type=2
and subjects.Sbj_IsVisible=1
and st.Sbj_IsVisible = 1
order by subjects.S_Level,
k.SD_Order
This partly works. When a parent subject is set to sbj_Isvisible 0, it does not return its children.
However, if the top most subject is set to sbj_IsVisible 1, the top most subject does not output, but its children do.
BTW, This is one a SQL Server 2008.
//edit
adding some example data.
This is the output of the original query:
ID ParentID Name Order Sbj_IsVisible
9017 0 'Boot Camp' 18 1
9033 9017 1 4 1
9049 9017 test 1 8 1
9050 9049 test 2 1 1
and this is the output of my query:
ID ParentID Name Order Sbj_IsVisible
9033 9017 1 4 1
9049 9017 test 1 8 1
9050 9049 test 2 1 1
here's the create table output:
USE [Fox8]
GO
/****** Object: Table [dbo].[Subjects_tbl] Script Date: 02/22/2012 16:25:12 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Subjects_tbl](
[S_ID] [int] IDENTITY(1,1) NOT NULL,
[S_TopID] [int] NULL,
[S_ParentID] [int] NULL,
[S_Name] [nvarchar](255) NULL,
[S_Order] [int] NULL,
[S_ItemCount] [int] NOT NULL,
[S_Level] [int] NULL,
[S_IsInherited] [int] NOT NULL,
[S_SortType] [nvarchar](50) NULL,
[S_SortOrder] [nvarchar](50) NULL,
[OriginalSbj_CourseID] [int] NULL,
[Sbj_CourseID] [int] NOT NULL,
[Sbj_IsVisible] [int] NULL,
[Sbj_SkinType] [int] NULL,
[CopyOf_SubjectID] [int] NULL,
[Sbj_GUID] [uniqueidentifier] NULL,
[Sbj_type] [int] NULL,
[s_OriginalSubjectID] [int] NULL,
[OriginalEvalTree_SbjId] [int] NULL,
[S_IsDeleted] [smallint] NOT NULL,
[S_DateDeleted] [datetime] NULL,
[S_IsPrimary] [bit] NULL,
CONSTRAINT [PK_Subjects] PRIMARY KEY CLUSTERED
(
[S_ID] ASC,
[S_ItemCount] ASC,
[Sbj_CourseID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
CONSTRAINT [UX_Subjects_S_ID_Sbj_CourseID] UNIQUE NONCLUSTERED
(
[S_ID] ASC,
[Sbj_CourseID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
EXEC sys.sp_addextendedproperty #name=N'MS_Description', #value=N'bitwise field 1 for regular subject 2 for weighted Subject 4 for X of Y Subject' , #level0type=N'SCHEMA',#level0name=N'dbo', #level1type=N'TABLE',#level1name=N'Subjects_tbl', #level2type=N'COLUMN',#level2name=N'Sbj_type'
GO
ALTER TABLE [dbo].[Subjects_tbl] ADD CONSTRAINT [DF_Subjects_S_ItemCount] DEFAULT ((0)) FOR [S_ItemCount]
GO
ALTER TABLE [dbo].[Subjects_tbl] ADD CONSTRAINT [DF_Subjects_S_IsInherited] DEFAULT ((1)) FOR [S_IsInherited]
GO
ALTER TABLE [dbo].[Subjects_tbl] ADD CONSTRAINT [DF_Subjects_Sbj_CourseID] DEFAULT ((-1)) FOR [Sbj_CourseID]
GO
ALTER TABLE [dbo].[Subjects_tbl] ADD DEFAULT ((0)) FOR [Sbj_SkinType]
GO
ALTER TABLE [dbo].[Subjects_tbl] ADD CONSTRAINT [DF_Subjects_Sbj_IsEvaluation] DEFAULT ((1)) FOR [Sbj_type]
GO
ALTER TABLE [dbo].[Subjects_tbl] ADD DEFAULT ((0)) FOR [S_IsDeleted]
GO
ALTER TABLE [dbo].[Subjects_tbl] ADD DEFAULT ((0)) FOR [S_IsPrimary]
GO
Your question is a little confusing to me but let me suggest using an OR clause, as in:
SELECT s.S_ID AS ID, s.S_ParentID AS ParentID, s.S_Name AS Name,
s.S_Order AS [Order], s.Sbj_IsVisible
FROM Subjects s
LEFT JOIN Subjects_tbl st ON s.S_ParentID = st.S_ID
LEFT JOIN KPI_SubjectDetails k ON s.S_ID = k.S_ID
WHERE s.Sbj_CourseID = 7594
AND s.Sbj_Type=2
AND s.Sbj_IsVisible = 1
AND (st.Sbj_IsVisible = 0 OR s.S_ParentID = 0)
ORDER BY s.S_Level, k.SD_Order
Essentially, select information from the subjects table if either it's corresponding parent is not visible or it does not have a corresponding parent (along with whatever your other conditions mean).
Hope that helps!