I want to add the total marks of different three table in my database and find the number of students whose marks is less than 80. So I did it this way:
SELECT
(SELECT SUM((totalmarks / 30) * 5) AS marks1 FROM marks) +
(SELECT SUM((totalmarks / 25) * 5) AS marks2 FROM marks2) +
(SELECT SUM((totalmarks / 15) * 5) AS marks3 FROM marks3) AS result
HAVING COUNT((result / 300) * 50) < 80
I am able to get the sum of the marks, but when I put HAVING COUNT condition, it shows nothing. Can someone tell me how to get the number of student using COUNT?
It shows error:
You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near 'HAVING COUNT((result/300)*50)>80' at line 11 .
Appreciate if someone can help me with this.
enter image description here
You need to group your results by student:
select studID, sum(result) * 5 as result
from (
select studID, totalmarks / 30 as result from marks1
union all
select studID, totalmarks / 25 as result from marks2
union all
select studID, totalmarks / 15 as result from marks3
) as base
group by studID
having ((result / 300) * 50) < 80
NB: it is a bit strange how you divide and multiply. For example, why not the equivalent:
having result < 480
If the logic is that in marks1 the highest possible score is 30, for marks2 25 and for marks3 15, and you want to give each of the three an equal weighting, then indeed you must divide each of the totalmarks as you do.
After the multiplication with five, this would mean the result can never be more than five.
So the having test is then quite superfluous: all results will be below 480.
So maybe you wanted to see who did not have the perfect score, for which the having clause should then be:
having result < 5
Using your current query, it needs a reference table/container to assess the HAVING condition.. so, here's my suggested solution:
SELECT result
FROM (
SELECT (
SELECT SUM(( totalmarks/30 )*5) AS marks1
FROM marks
) + (
SELECT SUM(( totalmarks/25 )*5) AS marks2
FROM marks2
) + (
SELECT SUM(( totalmarks/15 )*5) AS marks3
FROM marks3
) AS `result`
) AS `derived`
HAVING COUNT((result / 300) * 50) < 80
Related
I have table score like this.
Then I use query to get the maximum or highest average,
SELECT stud_num, assess_type, MAX(average) FROM score
WHERE assess_type = "general" OR assess_type = "professional"
OR assess_type = "specialization"
GROUP BY stud_num, assess_type;
Result is,
But I want to add every maximum value per ID and get the average.
like student #1 = 70 +80 / 3, student #2 = 62.5 + 76 + 72 / 3 etc.
It is possible to do this in one query?
Desire output is
stud_num | average
1 50 //avg of general, prof, special
2 71.5
3 72.16
This must solve your problem. Give it a try:
SELECT stud_num
, (SUM(max_average)/3) as final_average
, access_type
FROM
( SELECT stud_num
, access_type
, MAX(average) as max_average
from score
where access_type IN ('general', 'professional', 'specialization')
GROUP
BY stud_name
, access_type
) as temp_score
GROUP
BY stud_num
I am trying to convert numbers to a character representation.
I have a column named salary and it stores a value, e.g. 400 for employee 1. I want to display the salary of employee 1 with a select query. But, if a salary is 200 then display the salary as *, and if salary is 400 display ** and if salary is 600 than display ***.
So each * = 200
Can any one guide me how to do this ?
If there are a limited number of options (less than maybe 10), you want a case statement - https://dev.mysql.com/doc/refman/5.0/en/control-flow-functions.html#operator_case.
If you want many many asterisks if someone's salary is 10,000, you could use a little logic around rpad - http://www.w3resource.com/mysql/string-functions/mysql-rpad-function.php.
This is a very trivial problem.
You have tagged it with both mysql and sql-server; these are different tools with different language variations. The answer below will work with mysql but may need some refactoring for sql-server.
Select name
, concat(salary,rpad('',floor(salary/200),'*'))
From your table
...
SQL Server:
create table #tab (
name nvarchar(100),
salary int
)
insert #tab values ('Mrs. Garrett', 100), ('Mr. Drummond', 200),
('Kimberly', 300), ('Willis', 400),
('Arnold', 500), ('Tooty', 600),
('Natalie', 700)
select name,
salary,
replicate('*', floor(salary/200))
from #tab
drop table #tab
Which produces:
name salary (No column name)
Mrs. Garrett 100
Mr. Drummond 200 *
Kimberly 300 *
Willis 400 **
Arnold 500 **
Tooty 600 ***
Natalie 700 ***
Alternatively, you could replace the replicate() with this:
case
when salary >= 600 then '***'
when salary >= 400 then '**'
when salary >= 200 then '*'
else ''
end
In MySQL you can use RPAD
SELECT RPAD('',FLOOR(salary/200), '*') AS stars
FROM table_name
And in SQL Server, you can use REPLICATE
;WITH C AS(
SELECT 200 AS salary
UNION ALL
SELECT 400 AS salary
UNION ALL
SELECT 600 AS salary
UNION ALL
SELECT 200 AS salary
UNION ALL
SELECT 200 AS salary
)
SELECT REPLICATE('*', salary/200) AS stars
,salary/200 AS salary
FROM C
Output
stars salary
* 1
** 2
*** 3
* 1
* 1
This question already has answers here:
Implement paging (skip / take) functionality with this query
(6 answers)
Closed 1 year ago.
I have this query with MySQL:
select * from table1 LIMIT 10,20
How can I do this with SQL Server?
Starting SQL SERVER 2005, you can do this...
USE AdventureWorks;
GO
WITH OrderedOrders AS
(
SELECT SalesOrderID, OrderDate,
ROW_NUMBER() OVER (ORDER BY OrderDate) AS 'RowNumber'
FROM Sales.SalesOrderHeader
)
SELECT *
FROM OrderedOrders
WHERE RowNumber BETWEEN 10 AND 20;
or something like this for 2000 and below versions...
SELECT TOP 10 * FROM (SELECT TOP 20 FROM Table ORDER BY Id) ORDER BY Id DESC
Starting with SQL SERVER 2012, you can use the OFFSET FETCH Clause:
USE AdventureWorks;
GO
SELECT SalesOrderID, OrderDate
FROM Sales.SalesOrderHeader
ORDER BY SalesOrderID
OFFSET 10 ROWS
FETCH NEXT 10 ROWS ONLY;
GO
http://msdn.microsoft.com/en-us/library/ms188385(v=sql.110).aspx
This may not work correctly when the order by is not unique.
If the query is modified to ORDER BY OrderDate, the result set returned is not as expected.
This is how I limit the results in MS SQL Server 2012:
SELECT *
FROM table1
ORDER BY columnName
OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY
NOTE: OFFSET can only be used with or in tandem to ORDER BY.
To explain the code line OFFSET xx ROWS FETCH NEXT yy ROW ONLY
The xx is the record/row number you want to start pulling from in the table, i.e: If there are 40 records in table 1, the code above will start pulling from row 10.
The yy is the number of records/rows you want to pull from the table.
To build on the previous example: If table 1 has 40 records and you began pulling from row 10 and grab the NEXT set of 10 (yy).
That would mean, the code above will pull the records from table 1 starting at row 10 and ending at 20. Thus pulling rows 10 - 20.
Check out the link for more info on OFFSET
This is almost a duplicate of a question I asked in October:
Emulate MySQL LIMIT clause in Microsoft SQL Server 2000
If you're using Microsoft SQL Server 2000, there is no good solution. Most people have to resort to capturing the result of the query in a temporary table with a IDENTITY primary key. Then query against the primary key column using a BETWEEN condition.
If you're using Microsoft SQL Server 2005 or later, you have a ROW_NUMBER() function, so you can get the same result but avoid the temporary table.
SELECT t1.*
FROM (
SELECT ROW_NUMBER OVER(ORDER BY id) AS row, t1.*
FROM ( ...original SQL query... ) t1
) t2
WHERE t2.row BETWEEN #offset+1 AND #offset+#count;
You can also write this as a common table expression as shown in #Leon Tayson's answer.
SELECT *
FROM (
SELECT TOP 20
t.*, ROW_NUMBER() OVER (ORDER BY field1) AS rn
FROM table1 t
ORDER BY
field1
) t
WHERE rn > 10
Syntactically MySQL LIMIT query is something like this:
SELECT * FROM table LIMIT OFFSET, ROW_COUNT
This can be translated into Microsoft SQL Server like
SELECT * FROM
(
SELECT TOP #{OFFSET+ROW_COUNT} *, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS rnum
FROM table
) a
WHERE rnum > OFFSET
Now your query select * from table1 LIMIT 10,20 will be like this:
SELECT * FROM
(
SELECT TOP 30 *, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS rnum
FROM table1
) a
WHERE rnum > 10
SELECT TOP 10 * FROM table;
Is the same as
SELECT * FROM table LIMIT 0,10;
Here's an article about implementing Limit in MsSQL Its a nice read, specially the comments.
This is one of the reasons I try to avoid using MS Server... but anyway. Sometimes you just don't have an option (yei! and I have to use an outdated version!!).
My suggestion is to create a virtual table:
From:
SELECT * FROM table
To:
CREATE VIEW v_table AS
SELECT ROW_NUMBER() OVER (ORDER BY table_key) AS row,* FROM table
Then just query:
SELECT * FROM v_table WHERE row BETWEEN 10 AND 20
If fields are added, or removed, "row" is updated automatically.
The main problem with this option is that ORDER BY is fixed. So if you want a different order, you would have to create another view.
UPDATE
There is another problem with this approach: if you try to filter your data, it won't work as expected. For example, if you do:
SELECT * FROM v_table WHERE field = 'test' AND row BETWEEN 10 AND 20
WHERE becomes limited to those data which are in the rows between 10 and 20 (instead of searching the whole dataset and limiting the output).
In SQL there's no LIMIT keyword exists. If you only need a limited number of rows you should use a TOP keyword which is similar to a LIMIT.
Must try. In below query, you can see group by, order by, Skip rows, and limit rows.
select emp_no , sum(salary_amount) from emp_salary
Group by emp_no
ORDER BY emp_no
OFFSET 5 ROWS -- Skip first 5
FETCH NEXT 10 ROWS ONLY; -- limit to retrieve next 10 row after skiping rows
Easy way
MYSQL:
SELECT 'filds' FROM 'table' WHERE 'where' LIMIT 'offset','per_page'
MSSQL:
SELECT 'filds' FROM 'table' WHERE 'where' ORDER BY 'any' OFFSET 'offset'
ROWS FETCH NEXT 'per_page' ROWS ONLY
ORDER BY is mandatory
This is a multi step approach that will work in SQL2000.
-- Create a temp table to hold the data
CREATE TABLE #foo(rowID int identity(1, 1), myOtherColumns)
INSERT INTO #foo (myColumns) SELECT myData order By MyCriteria
Select * FROM #foo where rowID > 10
SELECT
*
FROM
(
SELECT
top 20 -- ($a) number of records to show
*
FROM
(
SELECT
top 29 -- ($b) last record position
*
FROM
table -- replace this for table name (i.e. "Customer")
ORDER BY
2 ASC
) AS tbl1
ORDER BY
2 DESC
) AS tbl2
ORDER BY
2 ASC;
-- Examples:
-- Show 5 records from position 5:
-- $a = 5;
-- $b = (5 + 5) - 1
-- $b = 9;
-- Show 10 records from position 4:
-- $a = 10;
-- $b = (10 + 4) - 1
-- $b = 13;
-- To calculate $b:
-- $b = ($a + position) - 1
-- For the present exercise we need to:
-- Show 20 records from position 10:
-- $a = 20;
-- $b = (20 + 10) - 1
-- $b = 29;
If your ID is unique identifier type or your id in table is not sorted you must do like this below.
select * from
(select ROW_NUMBER() OVER (ORDER BY (select 0)) AS RowNumber,* from table1) a
where a.RowNumber between 2 and 5
The code will be
select * from limit 2,5
better use this in MSSQLExpress 2017.
SELECT * FROM
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) as [Count], * FROM table1
) as a
WHERE [Count] BETWEEN 10 and 20;
--Giving a Column [Count] and assigning every row a unique counting without ordering something then re select again where you can provide your limits.. :)
One of the possible way to get result as below , hope this will help.
declare #start int
declare #end int
SET #start = '5000'; -- 0 , 5000 ,
SET #end = '10000'; -- 5001, 10001
SELECT * FROM (
SELECT TABLE_NAME,TABLE_TYPE, ROW_NUMBER() OVER (ORDER BY TABLE_NAME) as row FROM information_schema.tables
) a WHERE a.row > #start and a.row <= #end
If i remember correctly (it's been a while since i dabbed with SQL Server) you may be able to use something like this: (2005 and up)
SELECT
*
,ROW_NUMBER() OVER(ORDER BY SomeFields) AS [RowNum]
FROM SomeTable
WHERE RowNum BETWEEN 10 AND 20
Suppose to have a Table person(ID,....., n_success,n_fails)
like
ID n_success n_fails
a1 10 20
a2 15 10
a3 10 1
I want to make a query that will return ID of the person with the maximum n_success/(n_success+n_fails).
example in this case the output I'd like to get is:
a3 0.9090909091
I've tried:
select ID,(N_succes/(n_success + n_fails)) 'rate' from person
with this query I have each ID with relative success rate
select ID,MAX(N_succes/(n_success + n_fails)) 'rate' from person
with this query just 1 row correct rate but uncorrect ID
How can I do?
MS SQL
SELECT TOP 1 ID, (`n_success` / (`n_success` + `n_fails`)) AS 'Rate' FROM persona
ORDER BY (n_success / (n_success + n_fails)) DESC
MySQL
SELECT `ID`, (`n_success` / (`n_success` + `n_fails`)) AS 'Rate' FROM `persona`
ORDER BY (`n_success` / (`n_success` + `n_fails`)) DESC
LIMIT 1
Lot of answers already. Check working code here on SQL Fiddle with the required output by your last edit.
SELECT `ID`, `n_success` 'rate'
FROM `persona`
ORDER BY (`n_success` / (`n_success` + `n_fails`)) DESC
LIMIT 1
It depends on your dialect of SQL, but in T-SQL it would be:
SELECT TOP 1 p.ID, p.n_success / (p.n_success + p.n_fails) AS Rate
FROM persona p
ORDER BY p.n_success / (p.n_success + p.n_fails) DESC
You can vary as necessary for other dialects (use LIMIT 1 for MySql and SQLite, for example).
select id, (n_success/(n_success + n_fails)) as rate from person
where (n_success/(n_success + n_fails)) =
(select max(n_success/(n_success + n_fails)) from person)
I know there's similar questions but none seem to apply as to what I want to do.
Given the following query that returns lets say 85 results.
SELECT * FROM tbl_name WHERE person = 'Tom';
And I have another query that's similar but returns 168 results.
SELECT * FROM tbl_name WHERE person = 'Bob';
I'm trying to get results in valid multiples of 50.
By just changing person value in the WHERE clause I want to have the expected output of Tom's 1st, 50th results. Which means 2 row results total.
Likewise Bob would have returned the 1st, 50th, 100th, 150th result. Which is 4 row results total.
Is it possible to do this with just MySQL?
Nailed it. Change the 50 for different increments. This assumes you meant that you wanted 1, 51, 101 (every 50th).
SELECT
returnTable.*
FROM (
SELECT
#rownum:=#rownum+1 AS rowNumber,
tbl_name.*
FROM forum_posts, (SELECT #rownum:=0) variableInit
WHERE tbl_name.person = 'Tom'
) AS returnTable
WHERE returnTable.rowNumber = 1
OR (returnTable.rowNumber - 1) MOD 50 = 0;
If you actually want 1, 50, 100, 150 then the following does that (removed -1 from the WHERE)
SELECT
returnTable.*
FROM (
SELECT
#rownum:=#rownum+1 AS rowNumber,
tbl_name.*
FROM forum_posts, (SELECT #rownum:=0) variableInit
WHERE tbl_name.person = 'Tom'
) AS returnTable
WHERE returnTable.rowNumber = 1
OR returnTable.rowNumber MOD 50 = 0;