sql inner join on blank table [closed] - c#

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I have a complicated query for simple thing, but I have managed to make it to work. The query works when idclient is 1, but when idclient is 5 there is a problem.
Problem is that that client didn't order anything, he just paid some amount. So there isn't a.price, practically whole table is blank, and I want result like -1200,00 or paid amount in minus. My problem is that first part of table does not exist so inner join is impossible, and there for second part is also non existing. Any suggestion for a "quick fix"? :)
SELECT SUM(a.price) - s.pay AS Remain
FROM (SELECT name,
( quantity * itprice ) * ( 100 - percent ) / 100 AS price,
idclient
FROM (SELECT order.iditem AS ID,
item.name,
SUM(order.quant) AS quantity,
order.percent,
item.itprice,
order.idclient
FROM item
inner join order
ON order.iditem = item.id
WHERE ( order.idclient = 1 )
GROUP BY order.iditem,
order.percent,
item.name,
item.itprice,
order.idclient) AS X) AS a
inner join (SELECT SUM(amount) AS Pay,
idcom
FROM payed
WHERE ( idcom = 1 )
GROUP BY idcom) AS s
ON a.idclient = s.idcom
GROUP BY s.idcom,
a.idclient,
s.pay
(there is maybe some typing error in code, but don't bother because I have translated my original code, so maybe some letter is lost in translation. Code is correct)

Is this always just fetching one row? At least it looks like it, and if that's the case you could just use variables with something like this:
declare #price decimal(10,2) = 0, #payment decimal(10,2) = 0
SELECT
#price = SUM(order.quant * item.itprice ) * ( 100 - order.percent ) / 100)
FROM
item
inner join order
ON order.iditem = item.id
WHERE
order.idclient = 1
SELECT
#payment = SUM(amount)
FROM
payed
WHERE
idcom = 1
select #price - #payment

Related

Use case with a variable to determine whether a count has to be returned or column list

I have a situation where on a dashboard, for pending approvals I am trying to show certain items as follows
Item 1 [Count]
Item 2 [Count]
Item 3 [Count]
The [Count] shows a numeric value of items pending approval. On click of each of these items, there is an associated table where the records are being shown.
The way of deriving these counts is very complex and I wish to avoid making duplicate queries for count for example query #1 as
SELECT COUNT(*)
FROM tableName
and then query #2 as
SELECT ColumnA, ColumnB, ColumnC
FROM tableName
Since these queries are being read into my C# application, until now I've been doing the following
var onlyCount = true;
var subQuery = onlyCount? "COUNT(*)": "ColumnA, ColumnB, ColumnC";
var query = $"SELECT {subQuery} FROM tableName";
But with an ever-growing list of columns that needs to be managed, this makes the code look ugly. With calculated data in the select list, Case(s), IIF(s) in the statement the above-said solution is no longer a "maintainable" solution. With the select query is something as demonstrated below even possible?
DECLARE #CountOnly AS BIT = 1
SELECT
CASE
WHEN #CountOnly = 1
THEN COUNT(*)
ELSE ColumnA, ColumnB, ColumnC
END
FROM
tableName
Have any one ever faced such a scenario? Or if you could point me in a direction where this can be handled better?
Side note: The above query is being passed into a SqlDataReader to fetch the data and show to the end user.
You may want to use something like this:
DECLARE #CountOnly AS BIT = 1
IF (#CountOnly = 1)
BEGIN
SELECT ColumnA, ColumnB, ColumnC
FROM MyTable
ELSE
SELECT COUNT(*)
FROM MyTable
END

mysql select error on c# but running on query builder in navicat

I am getting this error every-time I run this query on c#.
"You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ':= 0 + 1 as rnk1 from attendance_table, (select 0 := 0) r1 order by User_ID, V' at line 1"
When I run it on query builder problem does not occur everything is working fine. I have already added this line
cmd.Parameters.AddWithValue("#r1", 0);
cmd.Parameters.AddWithValue("#r2", 0);
can somebody help me with this?
Here's the select command.
select
t1.User_ID,concat(employee_profile.fname,' ',employee_profile.mname,' ',employee_profile.lname) as fullname,
CASE WHEN t1.Verify_State = '0' THEN t1.Verify_Date END AS time_in,
CASE WHEN t2.Verify_State = '1' THEN t2.Verify_Date END AS time_out,round(TIMESTAMPDIFF(minute,t1.Verify_Date,t2.Verify_Date)/60,2) as Total_hours_worked,timeshift.time_in,
timeshift.time_ou
from
(select * , #r1:=#r1+1 as rnk1 from attendance_table , (select #r1:=0) r1 order by User_ID, Verify_Date) as t1 join
(select * , #r2:=#r2+1 as rnk2 from attendance_table , (select #r2:=0) r2 order by User_ID, Verify_Date) as t2
on t1.User_ID=t2.User_ID
and t1.rnk1+1=t2.rnk2
and t1.Verify_State=0
and t2.Verify_State=1
left Join
employee_profile ON employee_profile.emp_id_no = t1.User_ID
left JOIN employee_timeshift ON employee_timeshift.emp_id_no = t1.User_ID
left JOIN timeshift on timeshift.id = employee_timeshift.timeshift_id
left JOIN timeshift_day on timeshift_day.timeshift_id = timeshift.id
where t1.Work_date BETWEEN '2018-04-09' AND '2018-04-14' and t1.Work_time <> t2.Work_time and timeshift_day.day_id = if(DATE_FORMAT(t1.Verify_Date,'%H:%i:%s') BETWEEN '02:00:00' and '06:00:00',(DAYOFWEEK(t1.Verify_Date) -1)-1,DAYOFWEEK(t1.Verify_Date)-1)
order by employee_profile.lname asc, t1.Verify_Date,t2.Verify_Date
With
cmd.Parameters.AddWithValue("#r1", 0);
you're replacing the #r1s in the query with 0 and thus create an assignment to a literal. E.g.
#r1:=#r1+1
becomes
0:=0+1
(assign 0to 0). That's no valid expression as values can only be assigned to variables.
Analog for #r2.
I guess you don't do that replacement, when you run the query directly, so it works there.
As you didn't post what you actually intended to do, I cannot give you any further advise.

SQL Statement Not Selecting

I'm using SQL Server in a C# project for a troubleshooting program and I have a table that contains ID,Question,QuestionId,Solution and Rank. I want there to be multiple solutions to a problem and the program will choose the best ranked solution, which is just chosen by the highest number which gets incremented every time it is correct. For this I have the following SQL statement:
sql = "SELECT Solution FROM dbo.Questions WHERE Rank=(SELECT MAX(Rank) FROM
dbo.Questions) AND QuestionId =" + questionId;
When I had just one solution available this worked fine, but when I have multiple solutions it doesn't.
You need to properly parameterize your queries. Bobby Tables: A guide to preventing SQL injection
sql = "SELECT Solution FROM dbo.Questions q WHERE Rank=(SELECT MAX(Rank) FROM
dbo.Questions i where i.QuestionId = q.QuestionId) AND q.QuestionId =" + questionId;
This makes sure the max(rank) returned by the subquery is the max(rank) of the solution for the QuestionId you are querying for.
You can also do this if you just want one Solution:
select top 1 Solution
from dbo.Questions q
where QuestionId = #QuestionId
order by [Rank] desc
You're selecting the max rank of all solutions and looking for the solution to a specified question with that rank.
Start at the beginning - select the possible solutions into a CTE
with solutions as(
SELECT Solution, Rank FROM dbo.Questions WHERE QuestionId = #questionId
)
... more to come
Given that, you can use a ranking function to rank all the possible solutions, by rank and select the one with the best rank (too many ranks in that sentence!)
with solutions as(
SELECT Solution, Rank() OVER (ORDER BY Rank DESC) as rank
FROM dbo.Questions WHERE QuestionId = #questionId
)
SELECT * FROM solutions WHERE rank = 1
This doesnt cover 2 solutions having an equal rank - you'll get 2 results from the query if 2 have the same rank. Two solutions there - consider using both.
Chose a tiebreaker column - perhaps the most recent - by adding a second column into the ORDER BY (...RANK() OVER (ORDER BY rank DESC, CreatedDate DESC)
Throw a TOP 1 into the final select (SELECT TOP 1 * FROM solutions WHERE rank = 1)
The record has the MAX rank may not have the questionId you given in the AND QuestionId =" + questionId;
You might try this, I have left the where clause outside of the CTE query so that you can also use the query to get a complete list of each question with it's max rank (if you leave out the questionId filter):
with [ctreMaxSolution] as
(
select [QuestionId]
, max([Rank]) as [Rank]
from [dbo].[Questions]
group by [QuestionId]
)
select *
from [dbo].[Questions] as [q]
inner join [cteMaxSolution] as [cms] on [q].[QuestionId] = [cms].[QuestionId]
and [q].[Rank] = [cms].[Rank]
where [q].[QuestionId] = #questionId;
I've used a SQL Server variable there, but you can make a stored procedure out of it or convert it to an ad-hoc query like in your question, totally up to you.
First make a filter by "questionId" and then "order By" rank.
try with this:
SELECT TOP 1 q.solution FROM dbo.Questions q WHERE q.QuestionId = #QuestionId
ORDER BY q.Rank desc
Hope this help!
Kindly modify your query as below.
sql = "SELECT Solution FROM dbo.Questions WHERE Rank in (SELECT MAX(Rank) FROM
dbo.Questions) AND QuestionId =" + questionId;
Here i have modified where rank "in" instead of "="

Column is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause

This may be a very silly mistake but I just can't fix it. I have 2 tables, Questions and Questions_Rating.
Questions:
question_id question user_id
------------------------------------------
1 'How to blablabla' 1
2 'bla bla bla' 1
Questions_Rating
In this table, users will rate questions either by +1 or -1
question_rating_id question_id user_id rate
------------------------------------------------------
1 1 2 (+1)
2 1 3 (+1)
3 1 4 ( 1)
Now I would simply like to fetch the question from the questions table, and the SUM of the rate in the questions_rating table for this question, which has an ID = 1.
String QUERY = "SELECT q.question, SUM(r.rate) FROM questions q, questions_rating r WHERE r.question_id = q.question_id AND q.question_id = 1";
And this is what I'm getting.
Column 'questions.question' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
I know that the SUM of the rate will return 1 row, and the question is supposedly 1 row, I can't figure out what's wrong with this query.
I am using SQL Server 2008.
You will have to Group the values as per the question so you need a
GROUP BY q.question
at the end of your query
Good Explanation here
You need the group by q.question in your SQL statement.
Your Sum is suppose to return only a single row against the table, since you are selecting a column along with the Sum you need to specify a group on the selected column. In your case it should be q.question, and sum will be applied to each group of questions.
SELECT q.question,SUM(r.rate) AS RateSum
FROM questions q,questions_rating r
WHERE r.question_id = q.question_id AND q.question_id=1
GROUP BY q.question
or (using ANSI 92 style joins)
SELECT q.question,SUM(r.rate) AS RateSum
FROM questions q INNER JOIN questions_rating r ON r.question_id = q.question_id
WHERE q.question_id=1
GROUP BY q.question
or (using subqueries)
SELECT q.question, (SELECT SUM(r.rate) FROM questions_rating r WHERE r.question_id = q.question_id) AS RateSum
FROM questions q
WHERE q.question_id=1
You are missing group by clause in your select statement.
As you have used sum() function which is an aggregate function
So you need to write group by for all the select columns.
String QUERY = "SELECT
q.question,
SUM(r.rate)
FROM
questions q,
questions_rating r
where
r.question_id = q.question_id AND
q.question_id=1
group by
q.question";

Hint for a C# and also an SQL Puzzle

I was browsing SO careers and came across a job that had a pdf with a couple of puzzles they wanted applicants to send in.
Although I'm not interested in the job, I read the questions anyway and had a play in Visual Studio / SMSS. The first question was fairly easy to solve although I couldn't think if any way to optimise it (I solved it in C#). The second puzzle only one obvious solution strikes me and I can't think of any others.
I'm not sure if it's bad to discuss these questions here though, but if anyone can give me some hints or perhaps suggest somewhere where I can ask this without creating any grief it'd be appreciated.
The questions are in here: http://www.debtx.com/doc/DebtX_Programming_Problems.pdf
I could let the first one slide but the second one has me stumped on other ways of solving it than the obvious. Shame there's no PM function on SO...
Boilerplate solution for the first part C#:
public static bool Compare(int[] num, int[] div)
{
for (int i = 0; i < num.Length; i++)
{
for (int j = 0; j < div.Length; j++)
{
if (num[i] % div[j] == 0)
return true;
}
}
return false;
}
My SQL Solutions
select Table1.Key1, Table1.Key2 from Table1 inner join Table2 on Table1.Key1 = Table2.key2 where IsDeleted=0
select * from Table1 where key1 in(select Key2 from Table2 where IsDeleted=0)
It all seems so samey though
couple of examples using pseudo SQL to not give too much away
Not In
SELECT * FROM TBL1
WHERE NOT IN (
SELECT FROM TBL2
WHERE Deleted=0 AND Tbl2.Key1= Tbl1.Key1 AND Tbl2.Key2=Tbl1.Key2
)
Not Exists
SELECT * FROM TBL1
WHERE NOT EXISTS (
SELECT FROM TBL2
WHERE Deleted =0 AND Tbl2.Key1= Tbl1.Key1 AND Tbl2.Key2=Tbl1.Key2
)
Outter Join Is Null
SELECT * FROM TBL1 LEFT JOIN TBL2
WHERE TBL2.Key1 IS NULL OR Deleted=0
One optimisation to the C# question is to sort the DIV array. You're more likely to find a match quickly starting with the smaller numbers.
EDIT: Another optimisation to the C# question may be to look at an approach similar to the Prime Number Sieve of Eratosthenes the general theory being that you pre-empt some results without having to perform the checks.
As for the SQL question, the three obvious (common) ways are as others have stated, a JOIN, an IN and an EXISTS.
Well which solution have you used already? Immediately I think it can be done using a subquery with IN, using a LEFT OUTER JOIN and filtering on NULL, or using EXISTS.
Spoiler alert!!!!!
SELECT
T1.key1,
T1.key2
FROM
Table1 T1
WHERE
NOT EXISTS
(
SELECT *
FROM
Table2 T2
WHERE
T2.key1 = T1.key1 AND
T2.key2 = T1.key2 AND
COALESCE(T2.IsDeleted, 0) <> 1
)
SELECT
T1.key1,
T1.key2
FROM
Table1 T1
LEFT OUTER JOIN Table2 T2 ON
T2.key1 = T1.key1 AND
T2.key2 = T1.key2 AND
COALESCE(T2.IsDeleted, 0) <> 1
WHERE
T2.key1 IS NULL
SELECT
T1.key1,
T1.key2
FROM
Table1 T1
WHERE
(
SELECT COUNT(*)
FROM
Table2 T2
WHERE
T2.key1 = T1.key1 AND
T2.key2 = T1.key2 AND
COALESCE(T2.IsDeleted, 0) <> 1
) = 0

Categories

Resources