Related
Suppose I've Table T and It has 3 Columns and 3rd Column contains 10 distinct values and I want to fetch 5 samples from Table T for each distinct value in column 3rd.
WITH T(A, B,C) AS(
SELECT 12,'Hi','One' FROM DUAL UNION ALL
SELECT 34,'Am','One' FROM DUAL UNION ALL
SELECT 6,'to','Two' FROM DUAL UNION ALL
SELECT 3,'do','Two' FROM DUAL UNION ALL
SELECT 5,'aim','Two' FROM DUAL UNION ALL
SELECT 6,'mine','Two' FROM DUAL UNION ALL
SELECT 4,'not','Three' FROM DUAL
)
select a,b,c from(
SELECT A,B,C,ROW_NUMBER() OVER(PARTITION BY c ORDER BY C DESC) AS R
FROM T)
where r = 1
or you could possibly try this:
SELECT MIN(T.A),
T.B,
t.c
FROM t
JOIN (SELECT C,
MAX(b) AS b
FROM T
GROUP BY C) Y ON Y.C = T.C
AND Y.B = T.B
GROUP BY t.c, t.b
So i have a table that looks something like this:
ID CUR_Valid
1 N
1 N
1 N
1 N
1 N
1 Y
2 N
2 N
2 Y
3 Y
So as you can see one ID can only be allowed to have one y. I want to write a statment that shows me the IDs that have no Y or more then one Y.
My code so far looks like this:
Select [BILL_ID]
,[Bill_MONTH]
,[CUR_VALID]
,COUNT(CUR_VALID)
FROM DB.dbo.table
WHERE CUR_VALID = 'Y'
GROUP BY [BILL_ID]
,[Bill_MONTH]
,[CUR_VALID]
Having COUNT(CUR_VALID) > 1 OR COUNT(CUR_VALID) <1
I'm not sure whats wrong. Can someone point me into the right direction?
Try this answer. Hope this helps you:
Select [BILL_ID]
,[Bill_MONTH]
,[CUR_VALID]
,COUNT(CUR_VALID)
FROM DB.dbo.table
--WHERE CUR_VALID = 'Y'
GROUP BY [BILL_ID]
,[Bill_MONTH]
,[CUR_VALID]
Having COUNT(CASE WHEN CUR_VALID = 'Y' THEN 1 END) > 1 OR COUNT(CASE WHEN CUR_VALID = 'Y' THEN 1 END) <1
When you put WHERE CUR_VALID = 'Y' condition, it remove the records which don't have the the Y.
Try this update for, number of IDs.
Select COUNT(1)[No of Ids]
FROM DB.dbo.table
GROUP BY [BILL_ID]
,[Bill_MONTH]
,[CUR_VALID]
Having COUNT(CASE WHEN CUR_VALID = 'Y' THEN 1 END) > 1 OR COUNT(CASE WHEN CUR_VALID = 'Y' THEN 1 END) <1
It returns the Number of Ids.
use
SQL Aliases
Count as totalValid
Select [BILL_ID]
,[Bill_MONTH]
,[CUR_VALID]
,COUNT(CUR_VALID) as totalValid
FROM DB.dbo.table
WHERE CUR_VALID = 'Y'
GROUP BY [BILL_ID]
,[Bill_MONTH]
,[CUR_VALID]
Having totalValid > 1 OR totalValid <1
here is a sample query that demonstrates the identification of one with no Y or one with two or more Y's
with dat
as
(
select 1 id,'N' cur_valid union all
select 1,'N' union all
select 1,'N' union all
select 1,'N' union all
select 1,'N' union all
select 1,'Y' union all
select 2,'N' union all
select 2,'N' union all
select 2,'Y' union all
select 3,'Y' union all
select 4,'Y' union all /* two Ys */
select 4,'Y' union all
select 5,'N' /* no Y */)
select id
from
(
select id,sum(case when cur_valid='Y' then 1 else 0 end) x
from dat
group by id
) ilv
where x<>1
this can be condensed to
with dat
as
(
select 1 id,'N' cur_valid union all
select 1,'N' union all
select 1,'N' union all
select 1,'N' union all
select 1,'N' union all
select 1,'Y' union all
select 2,'N' union all
select 2,'N' union all
select 2,'Y' union all
select 3,'Y' union all
select 4,'Y' union all /* two Ys */
select 4,'Y' union all
select 5,'N' /* no Y */)
select id
from dat
group by id
having sum(case when cur_valid='Y' then 1 else 0 end)<>1
It is possible to use self join like this
select d1.id, count(d2.id)
from (select id from dat group by id) d1
left join dat d2 on d1.id = d2.id and d2.cur_valid = 'Y'
group by d1.id
having count(d2.id) <> 1
demo - thanks #Abbennett for the data
If I have strings like this:
CC123484556
CC492014512
BUXT122256690
How can I manipulate code like this in MySQL to pull the first 4 values that are numbers ? There are various # of letters before numbers in other rows but the most important thing are the first 4 numbers that show up.
SELECT LEFT(alloy , 4) FROM tbl
So the desired result would be:
1234
4920
1222
Slow and ugly:
SELECT col,
SUBSTRING(tab.col, MIN(LOCATE(four_digits, tab.col,1)), 4) + 0 AS result
FROM (SELECT 'CC123484556' AS col UNION ALL
SELECT 'CC492014512' UNION ALL
SELECT 'BUXT122256690' UNION ALL
SELECT 'abced') tab
CROSS JOIN (
SELECT CONCAT(d1.z, d2.z, d3.z, d4.z) AS four_digits
FROM (SELECT '1' AS z UNION SELECT '2' UNION SELECT '3' UNION
SELECT '4' UNION SELECT '5' UNION SELECT '6' UNION
SELECT '7' UNION SELECT '8' UNION SELECT '9' UNION SELECT '0') d1
CROSS JOIN (SELECT '1' AS z UNION SELECT '2' UNION SELECT '3' UNION
SELECT '4' UNION SELECT '5' UNION SELECT '6' UNION
SELECT '7' UNION SELECT '8' UNION SELECT '9' UNION SELECT '0') d2
CROSS JOIN (SELECT '1' AS z UNION SELECT '2' UNION SELECT '3' UNION
SELECT '4' UNION SELECT '5' UNION SELECT '6' UNION
SELECT '7' UNION SELECT '8' UNION SELECT '9' UNION SELECT '0') d3
CROSS JOIN (SELECT '1' AS z UNION SELECT '2' UNION SELECT '3' UNION
SELECT '4' UNION SELECT '5' UNION SELECT '6' UNION
SELECT '7' UNION SELECT '8' UNION SELECT '9' UNION SELECT '0') d4
) sub
WHERE LOCATE(four_digits, tab.col,1) > 0
GROUP BY col;
Rextester Demo
Generate all 4 digit combinations, locate them in string and get substring with lowest index.
EDIT:
A bit faster approach:
SELECT col, SUBSTRING(col, MIN(i), 4) + 0 AS r
FROM (
SELECT col, SUBSTRING(tab.col, i , 4) + 0 AS result, i
FROM tab
CROSS JOIN (
SELECT CONCAT(d1.z, d2.z)+1 AS i
FROM (SELECT '1' AS z UNION SELECT '2' UNION SELECT '3' UNION
SELECT '4' UNION SELECT '5' UNION SELECT '6' UNION
SELECT '7' UNION SELECT '8' UNION SELECT '9' UNION SELECT '0') d1
CROSS JOIN (SELECT '1' AS z UNION SELECT '2' UNION SELECT '3' UNION
SELECT '4' UNION SELECT '5' UNION SELECT '6' UNION
SELECT '7' UNION SELECT '8' UNION SELECT '9' UNION SELECT '0') d2
) sub
WHERE i <= LENGTH(tab.col)-1
) sub
WHERE result <> 0
GROUP BY col;
Rextester Demo2
Get 4 character substring from beginning, convert implicitly to number, get number with lowest i.
Using locate(), least(), and substr()
SQLFiddle Demo
select col,SUBSTR(col,LEAST(
if (Locate(0,col) >0,Locate(0,col),999),
if (Locate(1,col) >0,Locate(1,col),999),
if (Locate(2,col) >0,Locate(2,col),999),
if (Locate(3,col) >0,Locate(3,col),999),
if (Locate(4,col) >0,Locate(4,col),999),
if (Locate(5,col) >0,Locate(5,col),999),
if (Locate(6,col) >0,Locate(6,col),999),
if (Locate(7,col) >0,Locate(7,col),999),
if (Locate(8,col) >0,Locate(8,col),999),
if (Locate(9,col) >0,Locate(9,col),999)
),4) as result from test;
Test Results:
mysql> create table test ( col varchar(15));
Query OK, 0 rows affected (0.70 sec)
mysql> insert into test (col) values
-> ('CC123484556'),
-> ('CC492014512'),
-> ('BUXT122256690');
Query OK, 3 rows affected (0.13 sec)
Records: 3 Duplicates: 0 Warnings: 0
Output:
mysql> select * from test;
+---------------+
| col |
+---------------+
| CC123484556 |
| CC492014512 |
| BUXT122256690 |
+---------------+
3 rows in set (0.00 sec)
mysql> select col,SUBSTR(col,LEAST(
-> if (Locate(0,col) >0,Locate(0,col),999),
-> if (Locate(1,col) >0,Locate(1,col),999),
-> if (Locate(2,col) >0,Locate(2,col),999),
-> if (Locate(3,col) >0,Locate(3,col),999),
-> if (Locate(4,col) >0,Locate(4,col),999),
-> if (Locate(5,col) >0,Locate(5,col),999),
-> if (Locate(6,col) >0,Locate(6,col),999),
-> if (Locate(7,col) >0,Locate(7,col),999),
-> if (Locate(8,col) >0,Locate(8,col),999),
-> if (Locate(9,col) >0,Locate(9,col),999)
-> ),4) as result from test;
+---------------+--------+
| col | result |
+---------------+--------+
| CC123484556 | 1234 |
| CC492014512 | 4920 |
| BUXT122256690 | 1222 |
+---------------+--------+
3 rows in set (0.00 sec)
This code returns me the most used words in a column in TEXT format called description and is on the table 'messages`.
However I can not stick this in the WHERE code:
messages.tag = 'HELLO'
I need it to do what it already does, but with this WHERE I tried this code and gave not sure:
SELECT message, count(message) as count
FROM (
SELECT
messages.id,
SUBSTRING_INDEX(SUBSTRING_INDEX(messages.message, ' ', count.n), ' ', -1) as message
FROM
(select (h*100+t*10+u+1) n from
(select 0 h union select 1 union select 2 union select 3 union select 4 union
select 5 union select 6 union select 7 union select 8 union select 9) A,
(select 0 t union select 1 union select 2 union select 3 union select 4 union
select 5 union select 6 union select 7 union select 8 union select 9) B,
(select 0 u union select 1 union select 2 union select 3 union select 4 union
select 5 union select 6 union select 7 union select 8 union select 9) C
) as count
INNER JOIN messages
ON CHAR_LENGTH(messages.message)-CHAR_LENGTH(REPLACE(messages.message, ' ',''))>=count.n-1
ORDER BY id, n
) x
WHERE LENGTH(message) >= 5
AND messages.tag = 'HELLO'
GROUP BY message
ORDER BY count DESC
LIMIT 10
You have to move that where clause into the subquery. The messages alias is not known in the outer query:
FROM (SELECT messages.id,
SUBSTRING_INDEX(SUBSTRING_INDEX(messages.message, ' ', count.n), ' ', -1) as message
FROM (select (h*100+t*10+u+1) n
from (select 0 h union select 1 union select 2 union select 3 union select 4 union
select 5 union select 6 union select 7 union select 8 union select 9) A,
(select 0 t union select 1 union select 2 union select 3 union select 4 union
select 5 union select 6 union select 7 union select 8 union select 9) B,
(select 0 u union select 1 union select 2 union select 3 union select 4 union
select 5 union select 6 union select 7 union select 8 union select 9) C
) count INNER JOIN
messages
ON CHAR_LENGTH(messages.message)-CHAR_LENGTH(REPLACE(messages.message, ' ','')) >= count.n-1
WHERE messages.tag = 'HELLO'
ORDER BY id, n
) x
The other condition stays in the outer query.
Try this,
I think messages.tag should be like, not equal to 'HELLO'
SELECT message, count(message) as count
FROM (
SELECT
messages.id,
SUBSTRING_INDEX(SUBSTRING_INDEX(messages.message, ' ', count.n), ' ', -1) as message
FROM
(
select (h*100+t*10+u+1) n
from
(
select 0 h union select 1 union select 2 union select 3 union select 4
union
select 5 union select 6 union select 7 union select 8 union select 9) A,
(select 0 t union select 1 union select 2 union select 3 union select 4
union
select 5 union select 6 union select 7 union select 8 union select 9) B,
(select 0 u union select 1 union select 2 union select 3 union select 4
union
select 5 union select 6 union select 7 union select 8 union select 9) C
) count
INNER JOIN messages
ON CHAR_LENGTH(messages.message)-CHAR_LENGTH(REPLACE(messages.message, ' ',''))>=count.n-1
WHERE messages.tag like '%HELLO%'
ORDER BY id, n
) x
WHERE LENGTH(message) >= 5
GROUP BY message
ORDER BY count DESC
LIMIT 10
I have 2 tables: _divions and _employee. In _employee there's a column division which is id_division in the table _division. I need to order them by the _division order first.
This table has a column order. I have tried this SQL statement, but it doesn't do much:
SELECT
e . *
FROM
`_employee` AS `e`
JOIN
`_division` AS d
ORDER BY
d.order,
e.division,
e.order
You missing ON clause. Try this
SELECT e.*
FROM _employee AS e
JOIN _division AS d ON d.id_division = e.division
// ^^^^ Missing
ORDER BY e.order
Below query may help. (Assuming there are divisions with no employees)
with employee as
(
select 'NISHA' ENAME, '10' EDIV FROM DUAL
UNION
SELECT 'ABC' ENAME, '10' EDIV FROM DUAL
UNION
SELECT 'DEF' ENAME, '15' EDIV FROM DUAL
UNION
SELECT 'GHI' ENAME, '20' EDIV FROM DUAL
),
DIVISION AS
(
SELECT '10' DIV_ID, 'INFO-TECH' DIV_DESC FROM DUAL
UNION
SELECT '15' DIV_ID, 'HUMAN RESOURCES' DIV_DESC FROM DUAL
UNION
SELECT '20' DIV_ID, 'SALES' DIV_DESC FROM DUAL
UNION
SELECT '25' DIV_ID, 'RESEARCH' DIV_DESC FROM DUAL
)
SELECT *
FROM EMPLOYEE, DIVISION WHERE
employee.EDIV (+) = DIVISION.DIV_ID
ORDER BY DIV_DESC, ENAME
If all employees would definitely have a division,then use employee.EDIV = DIVISION.DIV_ID instead of employee.EDIV (+) = DIVISION.DIV_ID