Returning Conditional Columns in SQL Server - sql-server

Complete SQL Server noob here. I'm not sure how to go about finding an answer to as I'm mostly not sure what to begin searching.
I have BLOG table in my SQL Server database that stores blog posts like so
ID Title DatePosted
-----------------------------------------------
1 Why Batman is Greater than Sup... 07/15/2017
2 10 Reasons Superman is the wor... 08/02/2017
3 Sick of Metropolis? Move to Go... 08/03/2017
I have another relational table that stores blogs that users have Liked, i.e.,
UserID PostID DateLiked
-------------------------------
232413 2 08/03/2017
232413 1 07/30/2017
234285 2 08/03/2017
Now what I'd like to do is call a simple SELECT * on my BLOG table, but pass in a UserID as an argument to that query to determine if the Blog was liked by said user, so my Result set would look something like so.
Given User ID: 232413
ID Title DatePosted IsLiked
--------------------------------------------------------
1 Why Batman is Greater than Sup... 07/15/2017 1
2 10 Reasons Superman is the wor... 08/02/2017 1
3 Sick of Metropolis? Move to Go... 08/03/2017 0
Is this possible in SQL Server/Database? Any tips or helpful reading is VERY much appreciated!

Assuming DateLiked column is nullable.
I am casting result of case to bit because I think you want it as Boolean value.
Passing userId parameter as #paramUserId
DECLARE #paramUserId AS INT;
SELECT b.Id,
b.Title,
b.DatePosted,
CAST(CASE WHEN sb.DateLiked IS NULL THEN 0 ELSE 1) AS BIT) AS IsLiked
FROM BLOG AS b
INNER JOIN storesBlogs AS sb ON b.ID = sb.PostID
WHERE sb.UserID = #paramUserId

It's the result on sqlite3.
select a.ID, a.Title, a.DatePosted, case UserId when 232413 then 1 else 0 end IsLiked from BLOG a inner join LikeTable b on a.id = b.post_id;
2|10 Reasons Superman is the wor...|08/02/2017|1
1|Why Batman is Greater than Sup...|07/15/2017|1
2|10 Reasons Superman is the wor...|08/02/2017|0
select a.ID, a.Title, a.DatePosted, case UserId when 232413 then 1 else 0 end IsLiked from BLOG a left join LikeTable b on a.id = b.post_id;
1|Why Batman is Greater than Sup...|07/15/2017|1
2|10 Reasons Superman is the wor...|08/02/2017|1
2|10 Reasons Superman is the wor...|08/02/2017|0
3|Sick of Metropolis? Move to Go...|08/03/2017|0
No result satisfies the PO's requirement, but statement#2 worth considering.

select id,title,dateposted,0 as IsLiked from blog where id not in (select postid from user_liked where userid =232413)
union
select id,title,dateposted,1 as IsLiked from blog where id in (select postid from user_liked where userid =232413)
order by IsLiked desc
Result -
id title dateposted IsLiked
1 Why Batman is Greater than Sup... 2017-07-15 1
2 10 Reasons Superman is the wor... 2017-08-02 1
3 Sick of Metropolis? Move to Go... 2017-08-03 0

Related

Sql Server Weird CASE Statement

I am attempting to do something, but I am not sure if it is possible. I don't really know how to look up something like this, so I'm asking a question here.
Say this is my table:
Name | Group
-----+--------
John | Alpha
Dave | Alpha
Dave | Bravo
Alex | Bravo
I want to do something like this:
SELECT TOP 1 CASE
WHEN Group = 'Alpha' THEN 1
WHEN Group = 'Bravo' THEN 2
WHEN Group = 'Alpha' AND
Group = 'Bravo' THEN 3
ELSE 0
END AS Rank
FROM table
WHERE Name = 'Dave'
I understand why this won't work, but this was the best way that I could explain what I am trying to do. Basically, I just need to know when one person is a part of both groups. Does anyone have any ideas that I could use?
You should create a column to hold the values you want to sum and sum them, probably easiest to do this via a subquery:
Select Name, SUM(Val) as Rank
FROM (SELECT Name, CASE WHEN Group = 'Alpha' THEN 1
WHEN Group = 'Bravo' THEN 2
ELSE 0 END AS Val
FROM table
WHERE Name = 'Dave') T
GROUP BY Name
You can add TOP 1 and ORDER BY SUM(Val) to get the top ranked row if required.
After reading your comment, it could be simplified further to:
Select Name, COUNT([GROUP]) GroupCount
FROM table
GROUP BY Name
HAVING COUNT([GROUP]) > 1
That will simply return all names where they have more than 1 group.

How to return a SQL Server view that can divide fees?

I know this is kind of odd but I was wondering if I can do it using PURELY SQL-T script language
So here is the question, imagine we have 2 tables
Table purchasing
purchase_id, payment_id, xxxx, xxxx
1 1
2 1
3 1
Table of payment
payment_id, processing fee, xxx, xxx
1 9
One payment record can be related to multiple purchase records. Kinda like a cart system that you can pay for all the stuff that's in your cart.
And I can now create a View in the SQLServer to return all the purchase record + fields in the payment table like this
The View
purchase_id, payment_id, processing_fee
1 1 9
2 1 9
3 1 9
But, as you can see, the processing fee really should be divided into 3 equal pieces, I want the view to show this
purchase_id, payment_id, processing_fee
1 1 3
2 1 3
3 1 3
Here comes the question, is it possible? And if that's possible, how?
Use OVER Clause, this was introduced in sqlserver 2005:
SELECT
pur.purchase_id,
pur.payment_id,
1.0 * pay.processing_fee /
count(*) over (partition by pur.payment_id) as calculated_processing_fee
FROM purchasing pur
JOIN payment pay ON pur.payment_id = pay.payment_id
It's possible, but I'm not sure it's wise, since processing_fee is a part of the payment table, and not of the purchasing table.
Here is one way of doing it:
;With cte as
(
SELECT payment_id, COUNT(purchase_id) As NumberOfPurchases
FROM purchasing
GROUP BY payment_id
)
SELECT purchase_id,
purchasing.payment_id,
processing_fee / NumberOfPurchases As processing_feePerPurchase
FROM purchasing
INNER JOIN cte ON(purchasing.payment_id = cte.payment_id)
INNER JOIN payment ON(p.payment_id = payment.payment_id)
Note: Code was written directly here, there might be some mistakes.
You can use COUNT(PU.payment_id)OVER(PARTITION BY PU.payment_id) to get the count of purchasing records for a payment record.
;WITH purchase(purchase_id,payment_id) as
(
SELECT 1,1
UNION ALL SELECT 2,1
UNION ALL SELECT 3,1
UNION ALL SELECT 3,2
), payment(payment_id,processingfee) as
(
SELECT 1,9
UNION ALL SELECT 2,10
)
SELECT PU.purchase_id,PU.payment_id,PA.payment_id,PA.processingfee / COUNT(PU.payment_id)OVER(PARTITION BY PU.payment_id)
FROM
purchase PU INNER JOIN payment PA ON PU.payment_id = PA.payment_id

MSSQL join tables w bit

I have three tables :
1) UserTable
UserId UserName
1 Mike
2 John
3 Jennifer
2) FormName
fID fName
1 edit
2 cafe
3 backoffice
3)User to form
fId UserId Allowed(bit)
1 1 0
2 1 1
3 1 1
2 2 1
3 2 0
The first table is the user table with user informations.
The second table is the form table where it stores form names of application
The third table is user level table where it says which user is allowed to open which form .
I want to create sql query where I can see all information in a single table like :
UserId USerName Edit Cafe BackOffice
1 mike 0 1 1
2 john 1 1 0
I think it is possbile with SQL Fiddle and Pivot but I am having hard time to figure the right code out .
You can use the PIVOT function, but you have to cast the allowed column to something other than a bit datatype. For example, the below casts it to an int:
select userid, username,
coalesce(Edit, 0) Edit,
coalesce(Cafe, 0) Cafe,
coalesce(BackOffice, 0) BackOffice
from
(
select u.userid,
u.username,
f.fname,
cast(allowed as int) allowed
from usertable u
inner join user_form uf
on u.userid = uf.userid
inner join formname f
on uf.fid = f.fid
) d
pivot
(
max(allowed)
for fname in (Edit, Cafe, BackOffice)
) piv;
See SQL Fiddle with Demo

How can I add an integer from another table to the current selected table in SQL Server?

Does anyone know how can I add an integer from another table to the current selected table in SQL Server?
For example:
I have 2 tables with the following information in each table
tableA:
id username point status country
1 alvin 1 1 U.S.A
2 alvin 1 1 U.S.A
3 amy 1 0 Australia
tableB:
id username point
1 amy 1
2 alvin 1
3 ken 1
How can I sum up the total points in tableA with also add in the sum points from tableB?
I tried the following code, but seem is not working and error display:
SELECT username, (COUNT(distinct a.point) + (SELECT SUM(a.point)
FROM tableB b WHERE b.username = a.username) AS 'Points', status, country
FROM tableA
GROUP BY aco.username
And the output I expected will be:
username Points status country
alvin 3 1 U.S.A
amy 2 0 Australia
WITH Results(username,point)
AS
(
SELECT username, point FROM TableA
UNION ALL
SELECT username, point FROM TableB
)
SELECT username, sum(point) AS Points FROM Results GROUP BY username
GO
EDIT
The question has changed, so now the solution should look like this
WITH Results(username,point,status, country)
AS
(
SELECT username, point, status, country FROM TableA
UNION ALL
SELECT username, point, null, null FROM TableB
)
SELECT username, sum(point) AS Points, max(status), max(country) FROM Results GROUP BY username
GO
What is WITH ?
What is UNION ?
You don't mention why Ken doesn't appear in the output table, I assume that TableA is the 'master' list. If so I would do the following INNER JOIN which is the most simple solution.
SELECT a.username AS Username, SUM(ISNULL(a.point,0)+ISNULL(b.point,0)) as Points,
MAX(a.Status) as Status, MAX(a.Country) as Country
FROM TableA a
INNER JOIN TableB b
ON a.username=b.username
GROUP BY a.username

TSQL: Get all rows for given ID

I am trying to output all of my database reports into one report. I'm currently using nested select statements to get each line for each ID (the number of ID's is unknown). Now I would like to return all the rows for every ID (e.g. 1-25 if there are 25 rows) in one query. How would I do this?
SELECT (
(SELECT ... FROM ... WHERE id = x) As Col1
(SELECT ... FROM ... WHERE id = x) As Col2
(SELECT ... FROM ... WHERE id = x) As Col3
)
EDIT: Here's an example:
SELECT
(select post_id from posts where report_id = 1) As ID,
(select isnull(rank, 0) from results where report_id = 1 and url like '%www.testsite.com%') As Main,
(select isnull(rank, 0) from results where report_id = 1 and url like '%.testsite%' and url not like '%www.testsite%') As Sub
This will return the rank of a result for the main domain and the sub-domain, as well as the ID for the posts table.
ID Main Sub
--------------------------------------
1 5 0
I'd like to loop through this query and change report_id to 2, then 3, then 4 and carry on until all results are displayed. Nothing else needs to change other than the report_id.
Here's a basic example of what is inside the tables
POSTS
post_id post report_id
---------------------------------------------------------
1 "Hello, I am..." 1
2 "This may take..." 2
3 "Bla..." 2
4 "Bla..." 3
5 "Bla..." 4
RESULTS
result_id url title report_id
--------------------------------------------------------
1 http://... "Intro" 1
2 http://... "Hello!" 1
3 http://... "Question" 2
4 http://... "Help" 3
REPORTS
report_id description
---------------------------------
1 Introductions
2 Q&A
3 Starting Questions
4 Beginner Guides
5 Lectures
The query will want to pull the first post, the first result from the main website (www) and the first result from a subdomain by their report_id. These tables are part of a complicated join structure with many other tables but for these purposes these tables are the only ones that are needed.
I've managed to solve the problem by creating a table, setting variables to take all the contents and insert them in a while loop, then selecting them and dropping the table. I'll leave this open for a bit to see if anyone picks up a better way of doing it because I hate doing it this way.
If you need each report id on its own column, take a look at the PIVOT/UNPIVOT commands.
Here's one way of doing it :
SELECT posts.post_id AS ID,
IsNull(tblMain.Rank, 0) AS Main,
IsNull(tblSub.Rank, 0) AS Sub
FROM posts
LEFT JOIN results AS tblMain ON posts.post_id = tblMain.report_id AND tblMain.url like '%www.testsite.com%'
LEFT JOIN results AS tblSub ON posts.post_id = tblSub.report_id AND tblSub.url like '%.testsite%' and tblSub.url not like '%www.testsite%'
That is one query? You've provided your own answer?
If you mean you want to return a series of 'rows' as, for some reason, 'columns', this ability does exist, but I can't remember the exact name. Possible pivot. But it's a little odd.
see if this is what you are looking
SELECT
CASE WHEN reports.id = 1 THEN reports.Name
ELSE "" AS Col1,
CASE WHEN reports.id = 2 THEN reports.Name
ELSE "" AS Col2
....
FROM reports
Best Regards,
Iordan
Assuming you have a "master" table of IDs (if not I suggest you do so for Foreign Key purposes):
SELECT (
(SELECT ... FROM ... WHERE id = m.ID) As Col1
(SELECT ... FROM ... WHERE id = m.ID) As Col2
(SELECT ... FROM ... WHERE id = m.ID) As Col3
)
FROM MasterIDs m
Depending on how much each report is similar,you may be able to speed that up by moving some of the logic out of the nested statements and into the main body of the query.
Possibly a better way of thinking about this is to alter each report statement to return (ID,value) and do something like:
SELECT
report1.Id
,report1.Value AS Col1
,report2.Value AS Col2
FROM (SELECT Id, ... AS Value FROM ...) report1
JOIN (SELECT Id, ... AS Value FROM ...) report2 ON report1.Id = report2.Id
again, depending on the similarity of your reports you could probably combine these in someway.

Resources