I can't get the following to work as expected, tried what I have seen in other examples and solutions but still can't this right.
Dim pos As String = Nothing
Try
OpenUserDB()
Dim cmd43 As MySqlCommand = New MySqlCommand("SELECT COUNT(id) AS position FROM users " & _
"WHERE user_id <= #UserID ORDER BY food_total DESC", connUser)
cmd43.Parameters.AddWithValue("#UserID", UserID)
Dim reader As MySqlDataReader = cmd43.ExecuteReader
If reader.Read() Then
pos = reader("position").ToString() & positionName(reader("position").ToString())
End If
Return pos
Catch ex As Exception
Dim err As New ErrorLog
err.logError(Format(Date.Now, "dd-MM-yyy hh:mm:ss ") & ex.ToString)
Return Nothing
Finally
CloseUserDB()
End Try
table users
| id | userID | food_total |
| 1 | g01 | 84 |
| 2 | g02 | 83 |
| 3 | g03 | 34 |
I queried with UserID = g02 with expected result being 2, but got 3.
The user is suppose to be the 2nd User but it returns the wrong position. Help will be appreciated.
you might want to something like this.
Where you rank them all in the inner query based on food_total...the the outer query selects the information of that specific userid including the rank.
SELECT Id,userId,rank
FROM
(SELECT Id,userID,
#rank := IFNULL(#rank,0)+1 as rank
FROM users
ORDER BY food_total DESC) AS T
WHERE T.userID = 'g02'
sqlfiddle
Somehow #TinTran solution did not work for me with vb.net, but the following work fine;
SELECT Id,userId,rank
FROM
SELECT Id,userID, #rank := IFNULL(#rank,0)+1 as rank
FROM users ORDER BY food_total DESC) AS T, (SELECT #rank:=0) R
WHERE T.userID = 'g02'
Related
I have the following code
Dim cmd As New MySqlCommand("SELECT IdNumber, COUNT(DISTINCT date) AS 'Attendance' FROM record WHERE MONTH(date) = MONTH(CURRENT_DATE()) AND YEAR(date) = YEAR(CURRENT_DATE()) GROUP BY idNumber ", cn)
Dim i As MySqlDataReader = cmd.ExecuteReader()
While i.Read
Label1.Text = i("SUM(Attendance)")
i.Close()
End While
I need to display the COUNT Column SUM in a label, but when i run the code i get the following error:
'Could not find specified column in results: SUM(Attendance)'
The COUNT Column(Attendance) is generated within the code to get specific COUNT of items in table record in a specific date period and returns the following:
+----------+------------+
| idNumber | Attendance |
+-----------------------+
| 88383 | 4 |
| 64785 | 2 |
+-----------------------+
and now i want to SUM those specific items and display them in a table like below:
Label = 6
If you only need to sum up all distinct date per IdNumber, you don't need to select idNumber then do a sub-query to sum up all attendance.
SELECT SUM(Attendance) as Label
from (
SELECT COUNT(DISTINCT date) AS 'Attendance'
FROM record
WHERE MONTH(date) = MONTH(CURRENT_DATE())
AND YEAR(date) = YEAR(CURRENT_DATE())
GROUP BY idNumber
);
Result:
Label
6
Thank you stackoverflow community! I have learned SO much from you over the years and I've recently created an account. I hope the answer to this question isn't obviously somewhere already, but I am going to go crossed eyed if I read another post. Here's my problem:
I recently used a nested SELECT to get the highest score for each of my students from a table. I did so by a little trick another post taught me. I can't find the exact post I learned it from, but here is a snippet that's essentially the same trick. I imagine, if you are well versed in sql, it's nothing new to you:
SELECT id, authorId, answer, votes
FROM ( SELECT id, authorId, answer, votes
FROM answers
ORDER BY votes DESC) AS h
GROUP BY authorId
The ORDER BY ____ DESC makes the last value, the highest overwrite all previous, so you end up with only it...if I understand correctly. So, that was great and I tailored it to my needs. The only problem is, now, I'd like to add one more feature to it and I'm racking my brain cells over it. I'm hoping some generous person will just straighten me out. I want to get a complete list of students from my "rosters" table and if there is no score for a given student, in my "holder" table, I'd like it to display a "0". Here is what I have, and I don't know exactly how to tweak it to do just that:
SELECT *
FROM (
SELECT
holder.id,
#IFNULL(holder.score, 0) AS score,
holder.score AS score,
holder.total,
holder.student_id AS stu_id,
holder.date AS date,
users.firstname AS first,
users.lastname AS last,
users.stu_number AS stuno,
assignments.name AS test,
rosters.p_id,
preps.period AS period,
preps.user
FROM holder
JOIN rosters
ON rosters.stu_id = holder.student_id
JOIN users
ON users.id = holder.student_id
JOIN assignments
ON assignments.id = holder.t_id
JOIN preps
ON preps.id = rosters.p_id
WHERE holder.visible = 0
AND preps.user = 1
AND assignments.user = 1
AND holder.t_id = 1
AND preps.period = 2
ORDER BY score DESC
) x
GROUP BY stuno
ORDER BY last
You can see that line I commented out is one of my feeble attempts to get it to display a "0" if NULL, but it's not working. I get a complete list, but if the score isn't found for a student, that student isn't showing up in my list. Anyone have a solution/idea for me to try?
Am I overusing JOINs and making my life harder than it needs to be? I'm mostly self-taught, so I know I have some holes in the fundamentals. It hasn't stopped me from creating some crazy cool projects though...but every now and then I'm sure I'm causing myself some unnecessary grief.
///////////////////////////////////////////////
Here is what I have done with the answer below, so that it grabs info from my tables:
SELECT au.stu_id,
COALESCE(t.id, 0) as id,
COALESCE(t.score , 0) as score
FROM rosters au
LEFT JOIN (
SELECT *
FROM (
SELECT a.*,
#rownum := if(#prev_value = student_id,
#rownum + 1,
1) rn,
#prev_value := student_id as prev
FROM holder a,
(SELECT #rownum := 0, #prev_value := '') r
ORDER BY student_id, score DESC
) T
WHERE T.rn = 1) T
ON au.stu_id = T.student_id
So, this is working great, except it doesn't show students who don't have scores for a given test. If their score isn't found in the "holder" table, I'd like it to show up as a "0".
/////////////////
Wait a minute! I may have mispoke...I think it is working correctly. I'll need to tweak a few things and get back to you. By the way, thanks SO much for taking the time to help me!
Your first aproach only work because a bad design on MySQL.
The right aproach should be
SQL Fiddle Demo
SELECT a.id, a.authorId, a.answer, a.votes
FROM ( SELECT authorId,
MAX(votes) as votes
FROM answers
GROUP BY authorId ) AS h
JOIN answers a
ON a.authorId = h.authorId
AND a.votes = h.votes;
OUTPUT
| id | authorId | answer | votes |
|----|----------|--------|-------|
| 2 | a | x2 | 21 |
| 4 | b | x1 | 23 | ==>
| 5 | b | x2 | 23 | ==> duplicates max value are possible
But this have issue if several answer has same score. You need to include some logic to decide which one to show.
Also you can use variable to get the highest score.
SELECT *
FROM (
SELECT a.*,
#rownum := if(#prev_value = authorId,
#rownum + 1,
1) rn,
#prev_value := authorId as prev
FROM answers a,
(SELECT #rownum := 0, #prev_value := '') r
ORDER BY authorId, votes DESC
) T
WHERE T.rn = 1;
OUTPUT
| id | authorId | answer | votes | rn | prev |
|----|----------|--------|-------|----|------|
| 4 | b | x1 | 23 | 1 | b | => only one is show but would
| 2 | a | x2 | 21 | 1 | a | be random unless you specify some rule.
Now for your question you also need to use LEFT JOIN instead of JOIN to get the students without scores.
Something like this
SELECT au.authorId,
COALESCE(t.id, 0) as id,
COALESCE(t.answer , 0) as answer ,
COALESCE(t.votes , 0) as votes
FROM authors au
LEFT JOIN (
SELECT *
FROM (
SELECT a.*,
#rownum := if(#prev_value = authorId,
#rownum + 1,
1) rn,
#prev_value := authorId as prev
FROM answers a,
(SELECT #rownum := 0, #prev_value := '') r
ORDER BY authorId, votes DESC
) T
WHERE T.rn = 1) T
ON au.authorId = T.authorId
OUTPUT
| authorId | id | answer | votes |
|----------|----|--------|-------|
| a | 2 | x2 | 21 |
| b | 4 | x1 | 23 |
| c | 0 | 0 | 0 |
These are my tables:
Table_Bill_Summary
| Date | PersonId | BillNo |
Table_Bill_Items
| BillNo | ItemId | Quantity |
Item_MasterTable
| ItemId | ItemName | ItemRate |
I am going to specify a PersonId. This is what I want to print:
SELECT *
FROM Table_Bill_Summary
WHERE PersonId=#X
(SELECT IM.ItemName,BI.Quantity,IM.ItemRate
FROM Table_Bill_Items AS BI
INNER JOIN Item_MasterTable AS IM ON BI.ItemId=IM.ItemId
WHERE BI.BillNo=??)
My result should look like:
23/04/2013 Person123 Bill32
Item20 23 100
Item21 20 200
Item23 1 300
23/04/2013 Person123 Bill39
Item2 2 100
Item11 40 800
Item43 1 700
I want a child Select Query to be run for each row retrieved by the parent Select query on the column BillNo
select FLD1,FLD2,FLD3 from
(
SELECT CAST(Date as varchar(10)) as FLD1 ,CAST(PersonId as varchar(10)) as FLD2,
cast(BillNo as varchar(10)) as FLD3,1 as FLD4, Billno as fld5
FROM Table_Bill_Summary WHERE PersonId =#X
union
SELECT CAST(IM.ItemName as varchar(10)) as FLD1 ,CAST(BI.Quantity as varchar(10)) as FLD2,CAST(IM.ItemRate as varchar(10)) as FLD3 ,2 as FLD4, BS.Billno as fld5
FROM Table_Bill_Summary BS inner join Table_Bill_Items AS BI on bs.BillNo=BI.BillNo
INNER JOIN Item_MasterTable AS IM ON BI.ItemId=IM.ItemId
WHERE Bs.PersonId =#X
) as x order by fld5,fld4
You can't do this in SQL. Instead, perform the operation in your application by fetching the joined results (bills and items) sorted by bill and keeping track of the last seen bill when iterating through the resultset:
string stm = #"
SELECT BillNo, Date, ItemName, Quantity, ItemRate
FROM Table_Bill_Summary
JOIN Table_Bill_Items USING (BillNo)
JOIN Item_MasterTable USING (ItemId)
WHERE PersonId = #Person
ORDER BY BillNo
";
MySqlCommand cmd = new MySqlCommand(stm, conn);
cmd.Prepare();
cmd.Parameters.AddWithValue("#Person", person_id);
MySQLDataReader rdr = cmd.ExecuteReader();
bool isMore = rdr.Read();
while (isMore) {
int current_bill = rdr.GetInt32(0);
// output bill
do {
// output item
} while (isMore = rdr.Read() && rdr.GetInt32(0) == current_bill);
}
You can't. (At least not without some queer tricks ;-) An SQL select statement will always result in a list of rows showing the same columns.
You would usually solve this with a reporting software or with another programming language and GUI.
I'd like to count how many occurrences of a value happen before a specific value
Below is my starting table
+-----------------+--------------+------------+
| Id | Activity | Time |
+-----------------+--------------+------------+
| 1 | Click | 1392263852 |
| 2 | Error | 1392263853 |
| 3 | Finish | 1392263862 |
| 4 | Click | 1392263883 |
| 5 | Click | 1392263888 |
| 6 | Finish | 1392263952 |
+-----------------+--------------+------------+
I'd like to count how many clicks happen before a finish happens.
I've got a very roundabout way of doing it where I write a function to find the last
finished activity and query the clicks between the finishes.
Also repeat this for Error.
What I'd like to achieve is the below table
+-----------------+--------------+------------+--------------+------------+
| Id | Activity | Time | Clicks | Error |
+-----------------+--------------+------------+--------------+------------+
| 3 | Finish | 1392263862 | 1 | 1 |
| 6 | Finish | 1392263952 | 2 | 0 |
+-----------------+--------------+------------+--------------+------------+
This table is very long so I'm looking for an efficient solution.
If anyone has any ideas.
Thanks heaps!
This is a complicated problem. Here is an approach to solving it. The groups between the "finish" records need to be identified as being the same, by assigning a group identifier to them. This identifier can be calculated by counting the number of "finish" records with a larger id.
Once this is assigned, your results can be calculated using an aggregation.
The group identifier can be calculated using a correlated subquery:
select max(id) as id, 'Finish' as Activity, max(time) as Time,
sum(Activity = 'Clicks') as Clicks, sum(activity = 'Error') as Error
from (select s.*,
(select sum(s2.activity = 'Finish')
from starting s2
where s2.id >= s.id
) as FinishCount
from starting s
) s
group by FinishCount;
A version that leverages user(session) variables
SELECT MAX(id) id,
MAX(activity) activity,
MAX(time) time,
SUM(activity = 'Click') clicks,
SUM(activity = 'Error') error
FROM
(
SELECT t.*, #g := IF(activity <> 'Finish' AND #a = 'Finish', #g + 1, #g) g, #a := activity
FROM table1 t CROSS JOIN (SELECT #g := 0, #a := NULL) i
ORDER BY time
) q
GROUP BY g
Output:
| ID | ACTIVITY | TIME | CLICKS | ERROR |
|----|----------|------------|--------|-------|
| 3 | Finish | 1392263862 | 1 | 1 |
| 6 | Finish | 1392263952 | 2 | 0 |
Here is SQLFiddle demo
Try:
select x.id
, x.activity
, x.time
, sum(case when y.activity = 'Click' then 1 else 0 end) as clicks
, sum(case when y.activity = 'Error' then 1 else 0 end) as errors
from tbl x, tbl y
where x.activity = 'Finish'
and y.time < x.time
and (y.time > (select max(z.time) from tbl z where z.activity = 'Finish' and z.time < x.time)
or x.time = (select min(z.time) from tbl z where z.activity = 'Finish'))
group by x.id
, x.activity
, x.time
order by x.id
Here's another method of using variables, which is somewhat different to #peterm's:
SELECT
Id,
Activity,
Time,
Clicks,
Errors
FROM (
SELECT
t.*,
#clicks := #clicks + (activity = 'Click') AS Clicks,
#errors := #errors + (activity = 'Error') AS Errors,
#clicks := #clicks * (activity <> 'Finish'),
#errors := #errors * (activity <> 'Finish')
FROM
`starting` t
CROSS JOIN
(SELECT #clicks := 0, #errors := 0) i
ORDER BY
time
) AS s
WHERE Activity = 'Finish'
;
What's similar to Peter's query is that this one uses a subquery that's returning all the rows, setting some variables along the way and returning the variables' values as columns. That may be common to most methods that use variables, though, and that's where the similarity between these two queries ends.
The difference is in how the accumulated results are calculated. Here all the accumulation is done in the subquery, and the main query merely filters the derived dataset on Activity = 'Finish' to return the final result set. In contrast, the other query uses grouping and aggregation at the outer level to get the accumulated results, which may make it slower than mine in comparison.
At the same time Peter's suggestion is more easily scalable in terms of coding. If you happen to have to extend the number of activities to account for, his query would only need expansion in the form of adding one SUM(activity = '...') AS ... per new activity to the outer SELECT, whereas in my query you would need to add a variable and several expressions, as well as a column in the outer SELECT, per every new activity, which would bloat the resulting code much more quickly.
I have a table of people who have to confirm their assistance to an event. This event has limited capacity. I want to calculate the number of confirmed people and update the confirmation status within the same atomic query.
Let's say that PEOPLE table has id and confirmed fields.
I have tried something like this:
UPDATE PEOPLE
SET confirmed = 'Y'
WHERE
id = 'ID_VALUE'
AND
(
SELECT amount
FROM
(
SELECT
COUNT(*) AS amount
FROM
PEOPLE AS p
WHERE
p.confirmed = 'Y'
) AS aux1
) < CAPACITY_LIMIT
Example of table:
-------------------
| id | confirmed |
-------------------
| 1 | N |
-------------------
| 2 | N |
-------------------
| ... | ... |
-------------------
| 10 | N |
-------------------
If CAPACITY_LIMIT = 5 and I try to confirm sequentially from id = 1 to id = 10, I want to perform the update (confirm = 'Y') until id = 5.
I'm sure that I'm missing something, but I can't figure what is it.
Thanks in advance. Regards.
Try this:
UPDATE
PEOPLE AS p1
INNER JOIN
(SELECT COUNT(*) AS numConfirmed FROM PEOPLE AS p2 WHERE p2.confirmed = 'Y') aux
SET
p1.confirmed = 'Y'
WHERE
p1.id = 'ID_VALUE'
AND aux.numConfirmed < CAPACITY_LIMIT;
try this
SET #ct := (SELECT
COUNT(*) AS amount
FROM
PEOPLE AS p
WHERE
p.confirmed = 'Y');
UPDATE PEOPLE
SET confirmed = 'Y'
WHERE
id = '1'
AND CAPACITY_LIMIT < #ct
;
falvarez,
You might want to verify that your inputs('ID_VALUE',CAPACITY_LIMIT) are correct, including data type and actual value, since the same query works for me with no problem. The following is the query I run against my test table (as you can see the query skeleton is exactly same as yours):
update t_order set customer ='NewCustomerName' where id = 124 and
(select amount from (select count(*) as amount from t_order where customer is not null) as total) < 10