Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I have a column itemId that contains unique IDs in the format US001, US002, US003 etc.
The trailing numbers of these IDs are not consecutive as rows may have been deleted.
I am looking for a way to find the first number that DOES NOT EXIST in my column.
Example 1:
Column: US001, US002, US004, US006.
Expected result: 3.
Example 2:
Column: US001, US002, US003, US004, US007.
Expected result: 5.
Example 3:
Column: US001, US002, US003, US004, US005.
Expected result: 6.
I tried the following but this returns NULL or no results (also no error):
SELECT MIN((RIGHT(i.itemId, 3)) + 1) AS nextAvailableId
FROM items i
WHERE RIGHT(i.itemId, 3) NOT IN
(
SELECT * FROM
(
SELECT RIGHT(i2.itemId, 3) AS itemNo
FROM items i2
) AS x
)
Can anyone please help me with this ?
Thanks,
Tim
Here is one option using window functions and string functions:
select min(id) + 1 as nextAvailableId
from (
select substr(itemid, 2) as id,
lead(substr(itemid, 2)) over(order by substr(itemid, 2)) as lead_id
from mytable t
) t
where lead_id > id + 1 or lead_id is null
In MySQL 5.x, where string functions are not available, you can use a subquery:
select min(substr(itemid, 2)) + 1 as nextAvailableId
from mytable
where not exists (
select 1
from mytable t1
where substr(t1.itemid, 2) = substr(t.itemid, 2) + 1
)
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I have a Table with Column Headings:
ID Student_Name
Roll_Number
Subject1MarksObtained
Subject1TotalMarks
Subject2MarksObtained
Subject2TotalMarks
Subject3MarksObtained
Subject3TotalMarks
Subject4MarksObtained
Subject4TotalMarks
I want to write a query to output the results for individual student who have pass at least three of the subjects.
Without seeing the data, lets make some assumptions:
A pass is awarded for a subject if the marks obtained for that subject are equal to or more than 50% of the total marks available for that subject.
The name of the table is called Enrollment
To return a list of students who have passed at least 3 subjects we can use a query similar to the following:
This solution uses CASE to evaluate a 1 for a pass and a 0 for fail for each subject, then we sum those results and only return rows that have a score of 3 or more.
SELECT ID, Student_Name, Roll_Number
FROM Enrollment
WHERE
( CASE WHEN (Subject1MarksObtained / Subject1TotalMarks) >= 0.5 THEN 1 ELSE 0 END
+ CASE WHEN (Subject2MarksObtained / Subject2TotalMarks) >= 0.5 THEN 1 ELSE 0 END
+ CASE WHEN (Subject3MarksObtained / Subject3TotalMarks) >= 0.5 THEN 1 ELSE 0 END
+ CASE WHEN (Subject4MarksObtained / Subject4TotalMarks) >= 0.5 THEN 1 ELSE 0 END
) >= 3
There are different way to approach this, but this query is simple to read and gets the job done.
If you are querying an access table, then CASE WHEN is not supported but you can use IIF or SWITCH to achieve the same results:
SELECT ID, Student_Name, Roll_Number
FROM Enrollment
WHERE
( IIF( (Subject1MarksObtained / Subject1TotalMarks) >= 0.5, 1, 0)
+ IIF( (Subject2MarksObtained / Subject2TotalMarks) >= 0.5, 1, 0)
+ IIF( (Subject3MarksObtained / Subject3TotalMarks) >= 0.5, 1, 0)
+ IIF( (Subject4MarksObtained / Subject4TotalMarks) >= 0.5, 1, 0)
) >= 3
Let's instead start by fixing your broken schema. A normalised design might look somewhat as follows:
Student
ID
Student_Name
Roll_Number
Results
StudentID
Subject
Mark
This question already has answers here:
How to count items in comma separated list MySQL
(6 answers)
Closed 3 years ago.
I have a table looks like below:
ID path
| 1 YouTube,Newsletter,Social
| 2 YouTube,Newsletter
| 3 YouTube
Now I want to create a column to count the length of the path column. such as below:
ID path count weights
| 1 YouTube,Newsletter,Social 3 0.33
| 2 YouTube,Newsletter 2 0.5
| 3 YouTube 1 1
How do I do this?
I have tried JSON_LENGTH but couldn't get the command working.
PS. essentially I'm trying to replicate a query in PostgreSQL:
' select user_id, channels, 1.0 / array_length(channels, 1) as weights
from (
// ... query for marketing_channels as before)'
I am using MYSQL.
select d.email_entry_id
,d.channels
,JSON_LENGTH(d.channels)
from (
select email_entry_id
,group_concat(attribution_string order by visit_date asc separator ',' ) as channels
from database) d
error message: Error Code: 1370. execute command denied to user 'yb'#'%' for routine 'company.JSON_LENGTH'
Hope the question is clear enough. let me know if i need to clarify anything.
If I followed you correctly, you could simply extend the logic of your existing query (which, by the way, seems to be missing a GROUP BY clause). Instead of querying the aggregated data, it would be simpler to start from the original data, like:
SELECT
email_entry_id,
GROUP_CONCAT(attribution_string ORDER BY visit_date SEPARATOR ',' ) as channels,
COUNT(*) as `count`,
1/COUNT(*) as weight
FROM database
GROUP BY email_entry_id
There is a very common trick to achieve such outcome, demonstrated by following query
SELECT ID, PATH,
(LENGTH(PATH) - LENGTH(REPLACE(PATH, ',', ''))) + 1 COUNT
FROM DATABASE /* OR WHATEVER IS THE TABLE NAME */
The result
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I have the following table;
I want to get the sum of the sequence between the col1 and col2. So for example first row should be sum(7,8,9,10,11,12). Something similar to sum(seq(col1,col2)).
Can you please help me to write this in MySQL?
As we know the sum of N natural numbers would be n * (n + 1) / 2. Use the same concept to determine the sum of your columns.
Let's say col1 = 6 and col2 = 8, and as mentioned in comment col1 < col2, so the answer would be
Sum = Sum of (8) natural numbers - Sum of (6-1) natural numbers
SELECT
id,
col1,
col2,
(col2 * (col2 + 1) / 2) - ((col1 - 1) * col1 /2) Sum_Of_Col1_Col2
FROM table_name;
Something like this:
SELECT CASE WHEN MOD((col2-col1)/2)>0 THEN (col1+col2)*(col2-col1+1)/2 ELSE (col1+col2)*(col2-col1)/2+(col2+col1)/2 END AS col_sum
FROM yourTable
Your question might be a little hard to swing if you table doesn't also have some sort of ID or other unique column, so let's add that first:
id | col1 | col2
1 | 7 | 12
2 | 8 | 10
3 | 6 | 8
We can handle this via the "calendar table" approach, where in this case the calendar table just contains a sequence from 1 to however large the values can get. For example, in MySQL 8+ we can try:
WITH nums AS (
SELECT 1 AS val UNION ALL
SELECT 2 UNION ALL
...
SELECT 12
)
SELECT
t.id,
SUM(n.val) AS sum
FROM yourTable t
LEFT JOIN nums n
ON n.val BETWEEN t.col1 AND t.col2
GROUP BY
t.id
ORDER BY
t.id;
Demo
Note that there are better ways to generate a sequence table in MySQL other than a raw CTE, but this might the topic of a different question.
For your specific case where col2 > col1, there is a formula for summing up an arithmetic progression between two numbers. I have implemented it below
select ((col2−col1+1)*(col1+col2))/2 end as seq_sum
from your_table
Can also be expressed as:
select (square(col2)-square(col1)+col1+col2)/2 end as seq_sum
from your_table
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
Table:
From the above table, below query is not giving proper result.
SELECT * FROM `support_profile`
WHERE `packageName` LIKE 'Platinum' AND `columnValue` IN ('50','150');
Result:
I need a query for checking the data is changed or not for the perticular packageName and columnValue?
Here is the internal representation of IN
Where `columnValue` In (50) => Where (columnValue = 50)
Where `columnValue` In (50,100) => Where ( (columnValue = 50) OR (columnValue =100) )
Your query:
SELECT * FROM `support_profile`
WHERE `packageName` LIKE 'Platinum' AND `columnValue` IN ('50','150');
is equivalent to
SELECT * FROM `support_profile`
WHERE
(
(`packageName` LIKE 'Platinum')
AND
(
(`columnValue` = '50')
OR (`columnValue` = '100')
)
);
Which will return all Platinum with columnValue 50 or 100.
if you wish to return only platinum 50 or platinum 100, you can group them. (make sure which of the latest record you want by sorting the records)
SELECT * FROM `support_profile`
WHERE `packageName` LIKE 'Platinum' AND `columnValue` IN ('50','150')
GROUP BY `packageName`, `columnValue` ;
if you wish to know whether the package values have changed
SELECT * FROM `support_profile`, Count(distinct `columnValue`) as valueChanges
WHERE `packageName` LIKE 'Platinum' AND `columnValue` IN ('50','150')
GROUP BY `packageName` ;
you get
silver 2
gold 1
platinum 1
PS: Please do us a favor and search how to ask question here
If you want to get records which are IN (50,150) and don't want to compare package name then remove the like condition. Use query as below. I hope this help you to get exact output, and please post your expected output:
SELECT * FROM `support_profile` WHERE `columnValue` IN ('50','150');
If You want to check the data which are not match with 50 and 150 then you can try below query:
SELECT * FROM `support_profile` WHERE `packageName` LIKE 'Platinum' AND `columnValue` NOT IN ('50','150');
To check if both the data exist in table or not, use AND in WHERE as below:
SELECT * FROM `support_profile` WHERE `packageName` LIKE 'Platinum' AND `columnValue` = '50' AND `columnValue` = '150' ;
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 5 years ago.
Improve this question
I try get vacancies per course, cause have limited vacancies per course;
So a need return:
Course 1 - No vacancies
Course 2 - 2 vacancies
SELECT
curs.CURSO_ID,
curs.CURSO_NOME,
curs.CURSO_DATA_INICIO,
curs.CURSO_DATA_FIM,
curs.CURSO_DESCRICAO,
curs.CURSO_LINK,
cate.CAT_CUR_ID,
cate.CAT_CUR_DESCRICAO,
curs.CURSO_VAGAS,
(
SELECT COUNT(sol.SOLI_ID)
FROM
solicitacao AS sol
WHERE
sol.SOLI_FK_CURSO_ID = curs.CURSO_ID
) AS pedido,
IF (
curs.CURSO_VAGAS > pedido THEN (curs.CURSO_VAGAS - pedido) ELSE 0
) AS totalVagas
/** CASE WHEN (curs.CURSO_VAGAS > pedido) THEN (curs.CURSO_VAGAS - pedido) ELSE 0 END AS totalVagas **/
FROM
curso AS curs
LEFT JOIN curso_categoria AS cate ON cate.CAT_CUR_ID = curs.CURSO_FK_CATEGORIA_ID
ORDER BY
CURSO_DATA_INICIO ASC
Thanks for help
Try this IF syntax:
IF (curs.CURSO_VAGAS > (
SELECT COUNT(sol.SOLI_ID)
FROM solicitacao AS sol
WHERE
sol.SOLI_FK_CURSO_ID = curs.CURSO_ID
), (curs.CURSO_VAGAS - (
SELECT COUNT(sol.SOLI_ID)
FROM solicitacao AS sol
WHERE
sol.SOLI_FK_CURSO_ID = curs.CURSO_ID
)), 0) AS totalVagas
You can use alias name only in GROUP BY, ORDER BY, or HAVING clauses
Try another solution:
IF (curs.CURSO_VAGAS > (SELECT pedido), (curs.CURSO_VAGAS - (SELECT pedido )), 0) AS totalVagas