MYSQL sort words in field - mysql

Edit 1 the code is just an example, I do not have suburb data, my real data is inherited and messy and could be fixed by creating code out of the database or creating reference data. The question should have been something like does anyone have a good cell sort function or other solution that can be reused?
Table
CREATE TABLE postcode (
`id` int NOT NULL AUTO_INCREMENT,
`suburbs` varchar(2000) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_unicode_ci;
Insert
INSERT INTO postcode (`suburbs`)
VALUES ( 'Zackville;Astor;Mary-town;Jackson' );
Want field to be sorted an result to be
Astor;Jackson;Mary-town;Zackville

All comments have very valid points and you should try to avoid working with delimited values in RDBMS.
That being said, if you're stuck with the existing database and you for some reason want to do it on the database level rather than with client code you can leverage tally(number) table and SUBSTRING_INDEX() to split delimited values into rows, then GROUP_CONCAT() to pivot data back in the ordered manner.
One of the several ways to create a tally table:
CREATE TABLE tally (n int not null primary key);
INSERT INTO tally (n)
SELECT a.N + b.N * 10 + 1 n
FROM
(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
ORDER BY n
Number of rows in the tally table should be greater or equal to the maximum possible number of delimited values.
Now to resort delimited values:
UPDATE postcode p JOIN
(
SELECT id, GROUP_CONCAT(suburbs ORDER BY suburbs SEPARATOR ';') suburbs
FROM
(
SELECT t.id, SUBSTRING_INDEX(SUBSTRING_INDEX(t.suburbs, ';', n.n), ';', -1) suburbs
FROM postcode t CROSS JOIN tally n
WHERE n.n <= 1 + (LENGTH(t.suburbs) - LENGTH(REPLACE(t.suburbs, ';', '')))
) q
GROUP BY id
) s
ON p.id = s.id
SET p.suburbs = s.suburbs;
Output:
| ID | SUBURBS |
|----|-----------------------------------|
| 1 | Astor;Jackson;Mary-town;Zackville |
Here is a SQLFiddle demo

Related

Splitting string in mysql every n value

I have this blob field in a MySQL database and its quite lengthy and I'm needing to split up the values every 4 bytes, the data is displayed in hex variables.
7A080040950507000100000000000000320900420200000002000000C04D032E1841712CFFFFFFFF4E0000000100000000000000AD95014202000000020000004040032E78FD712CFFFFFFFFA89C0B0001000000000000003209004202000000020000004040032E1841712C96080040FFFFFFFF01000000F4B55D0CA79501420200000002000000C04D032E10E8712CFFFFFFFF7F4310000100000000000000AD950142020000000200000040CBFA2D78FD682CFFFFFFFF0000000001000000000000003F090042020000000200000040CBFA2D401F6F2CFFFFFFFF0000000000000000000000000000000000000000000000000000000000000000FFFFFFFF0000000000000000000000000000000000000000000000000000000000000000FFFFFFFF0000000000000000000000000000000000000000000000000000000000000000FFFFFFFF0000000000000000000000000000000000000000000000000000000000000000FFFFFFFF0000000001000000000000004E06004202000000F4011C10C0C7B82EF8A9652CFFFFFFFF000000000100000000000000AA06004202000000020000004040032E4873682CFFFFFFFF000000000100000000000000AA060042020000000200000040CBFA2D20805F2CFFFFFFFF000000000100000000000000360600420
This is a sample of the data and I'm just wanting to split it up to look like 7A08 0040 9505 0700 0100 0000 0000 0000 3209 0042 and so on to place into their own columns.
I've done a lot of searching but I've not been able to find anything that will allow me to do what I'm asking and any help would be appreciated. I need to be able to do this in MySQL only.
If you just need to split up the data you can use Substring('Text',start,length).
However to assign values to an unspecified number of columns, is not how SQL normally work. I would suggest you make a subtable to contain the substrings and relate the main table to the subtable with af key.
DECLARE #text NVARCHAR(1000)
DECLARE #text_Sub NVARCHAR(10)
DECLARE #i int -- integration variable
DECLARE #foreignKey int --relation key to main table
SET #foreignKey = 1 -- Must be adjusted for each string you want to pass
SET #text = '0x7A080040950507000100000000000000320900420200000002000000C04D032E1841712CFFFFFFFF4E0000000100000000000000AD95014202000000020000004040032E78FD712CFFFFFFFFA89C0B0001000000000000003209004202000000020000004040032E1841712C96080040FFFFFFFF01000000F4B55D0CA79501420200000002000000C04D032E10E8712CFFFFFFFF7F4310000100000000000000AD950142020000000200000040CBFA2D78FD682CFFFFFFFF0000000001000000000000003F090042020000000200000040CBFA2D401F6F2CFFFFFFFF0000000000000000000000000000000000000000000000000000000000000000FFFFFFFF0000000000000000000000000000000000000000000000000000000000000000FFFFFFFF0000000000000000000000000000000000000000000000000000000000000000FFFFFFFF0000000000000000000000000000000000000000000000000000000000000000FFFFFFFF0000000001000000000000004E06004202000000F4011C10C0C7B82EF8A9652CFFFFFFFF000000000100000000000000AA06004202000000020000004040032E4873682CFFFFFFFF000000000100000000000000AA060042020000000200000040CBFA2D20805F2CFFFFFFFF000000000100000000000000360600420'
-- this should be permanent table
CREATE TABLE #TempTable(
Id INT IDENTITY(1,1),
ForeignKey int,
Text NVARCHAR(10)
)
-- loop over text and insert into af subtable
SET #i = 0
SET #text_Sub = SUBSTRING(#text,#i,10)
WHILE (LEN(#text_Sub) > 0)
BEGIN
INSERT INTO #TempTable
( ForeignKey,Text)
VALUES
( #foreignKey,#text_Sub)
SET #i = #i +10
SET #text_Sub = SUBSTRING(#text,#i,10)
END
--Test the subtable have been filled
SELECT COUNT( *),MAX(Id)
FROM #TempTable
-- Assume you have a table called Table insert the relationkey/foreignKey
-- INSERT INTO Table
-- (ForeignKey)
-- VALUES
-- (#foreignKey)
-- WHERE 'SomeIdentifier'
--Clean up the temp table
DROP TABLE #TempTable
WITH RECURSIVE
cte AS ( SELECT UNHEX(LEFT(HEX(val), 8)) part,
UNHEX(SUBSTRING(HEX(val) FROM 9)) slack
FROM test
UNION ALL
SELECT UNHEX(LEFT(HEX(slack), 8)),
UNHEX(SUBSTRING(HEX(slack) FROM 9))
FROM cte
WHERE slack != '' )
SELECT part
FROM cte;
fiddle
That would work except I'm having to use MySQL 5.6 for the program to work properly.
SELECT /* UNHEX(SUBSTRING(HEX(val) FROM 1+8*(num1.num*100+num2.num*10+num3.num) FOR 8)) part */
SUBSTRING(HEX(val) FROM 1+8*(num1.num*100+num2.num*10+num3.num) FOR 8) part
FROM test
JOIN (SELECT 0 num 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) num1
JOIN (SELECT 0 num 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) num2
JOIN (SELECT 0 num 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) num3
HAVING part != ''
ORDER BY num1.num*100+num2.num*10+num3.num
The query assumes that max. length of BLOB value is 4000 bytes. If the length is greater then add proper numN tables count.

Count group by enum including possible enum values that have 0 count

I have a table of items. One of the fields is a category (represented by an enum). Some categories have zero items.
So I did this:
select category, count(*) as total from items group by category;
+------------+-------+
| category | total |
+------------+-------+
| one | 6675 |
+------------+-------+
I want to generate a table like this (where two is the other possible enum value):
+------------+-------+
| category | total |
+------------+-------+
| one | 6675 |
+------------+-------+
| two | 0 |
+------------+-------+
How do I do this with an mysql SQL query?
Enum datatype is generally preferred for those cases where possible options (values) are not too many (prefer <= 10), and you are not going to add new options in future (atleast not very frequently). So, a good use-case for Enum is gender: (m, f, n). In your case, it would be generally better to have a Master table of all possible Categories, instead of using Enum for them. Then it is easier to do a LEFT JOIN from the Master table.
However, as asked by you:
A solution uses the enum type to generate the table, and includes 0
entries
Works for all MySQL/MariaDB versions:
We will need to get the list of all possible Enum values from INFORMATION_SCHEMA.COLUMNS:
SELECT
SUBSTRING(COLUMN_TYPE, 6, CHAR_LENGTH(COLUMN_TYPE) - 6) AS enum_values
FROM
information_schema.COLUMNS
WHERE
TABLE_NAME = 'items' -- your table name
AND
COLUMN_NAME = 'category' -- name of the column
AND
TABLE_SCHEMA = 'your_db' -- name of the database (schema)
But then, this query will give you all the enum values in comma-separated string, like below:
'one','two','three','four'
Now, we will need to convert this string into multiple rows. To achieve that, we can use a Sequence (Number series) table. You can define a permanent table in your database storing integers ranging from 1 to 100 (you may find this table helpful in many other cases as well) (OR, another approach is to use a Derived Table - check this to get an idea: https://stackoverflow.com/a/58052199/2469308).
CREATE TABLE seq (n tinyint(3) UNSIGNED NOT NULL, PRIMARY KEY(n));
INSERT INTO seq (n) VALUES (1), (2), ...... , (99), (100);
Now, we will do a JOIN between "enum values string" and seq table, based on the position of comma, to extract enum values into different rows. Note that instead of just using , (comma) to extract enum values, we would use ',' (to avoid cases when there might be a comma inside the value string). String operations utilizing Substring_Index(), Trim(), Char_Length() etc functions can be used to extract enum values. You can check this answer to get a general idea about this technique:
Schema (View on DB Fiddle)
CREATE TABLE items
(id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
category ENUM('one','two','three','four'),
item_id INT UNSIGNED) ENGINE=InnoDB;
INSERT INTO items (category, item_id)
VALUES ('one', 1),
('two', 2),
('one', 2),
('one', 3);
CREATE TABLE seq (n tinyint(3) UNSIGNED NOT NULL,
PRIMARY KEY(n));
INSERT INTO seq (n) VALUES (1),(2),(3),(4),(5);
Query #1
SELECT Trim(BOTH '\'' FROM Substring_index(Substring_index(e.enum_values,
'\',\'',
seq.n),
'\',\'', -1)) AS cat
FROM (SELECT Substring(column_type, 6, Char_length(column_type) - 6) AS
enum_values
FROM information_schema.columns
WHERE table_name = 'items'
AND column_name = 'category'
AND table_schema = 'test') AS e
JOIN seq
ON ( Char_length(e.enum_values) - Char_length(REPLACE(e.enum_values,
'\',\'',
''))
) / 3 >= seq.n - 1
| cat |
| ----- |
| one |
| two |
| three |
| four |
Now, the hard part is done. All we need to do is do a LEFT JOIN from this subquery (having all category enum values) to your items table, to get Count per category.
The final query follows (View on DB Fiddle):
SELECT all_cat.cat AS category,
Count(i.item_id) AS total
FROM (SELECT Trim(BOTH '\'' FROM Substring_index(
Substring_index(e.enum_values,
'\',\'',
seq.n),
'\',\'', -1)) AS cat
FROM (SELECT Substring(column_type, 6, Char_length(column_type) - 6)
AS
enum_values
FROM information_schema.columns
WHERE table_name = 'items'
AND column_name = 'category'
AND table_schema = 'test') AS e
JOIN seq
ON ( Char_length(e.enum_values) - Char_length(
REPLACE(e.enum_values,
'\',\'',
''))
) / 3 >= seq.n - 1) AS all_cat
LEFT JOIN items AS i
ON i.category = all_cat.cat
GROUP BY all_cat.cat
ORDER BY total DESC;
Result
| category | total |
| -------- | ----- |
| one | 3 |
| two | 1 |
| three | 0 |
| four | 0 |
Here is some fun with MySQL 8.0 and JSON_TABLE():
select c.category, count(i.category) as total
from information_schema.COLUMNS s
join json_table(
replace(replace(replace(trim('enum' from s.COLUMN_TYPE),'(','['),')',']'),'''','"'),
'$[*]' columns (category varchar(50) path '$')
) c
left join items i on i.category = c.category
where s.TABLE_SCHEMA = 'test' -- replace with your db/schema name
and s.TABLE_NAME = 'items'
and s.COLUMN_NAME = 'category'
group by c.category
It converts the ENUM type definition from information_schema to a JSON array, which is then converted by JSON_TABLE() to a table, which you then can use for a LEFT JOIN.
See demo on db-fiddle
Note: The categories should not contain any characters from ()[]'".
But seriously – Just create the categories table. There are more reasons to do that. For example you might want to render a drop-down menu with all possible categories. That would be simple with
select category from categories
I would say that it's basically bad practice to encode your enumerations into the script. Therefore, create a table with the enumerations present (and their relative keys), then it's a simple case of grouping a left joined query...
SELECT
cat.enum_name,
COUNT(data.id) AS total
FROM
category_table cat
LEFT JOIN
data_table data
ON cat.cate_id = data.cat_id
GROUP BY
cat.enum_name
using in-select subquery
select cat.categoryname
(
select count(*) -- count total
from items as i
where i.category = cat.category -- connect
) as totalcount
from cat
order by cat.categoryname
You can make a fictive dataset of the different categories and do a left join with your original table as shown below.
SELECT A.category, count(*) total FROM
(SELECT 'one' as Category
UNION ALL
SELECT 'two' as Category) A
LEFT JOIN items B
ON A.Category=B.Category
GROUP BY B.Category;
If you would prefer to get a list of all the category dynamically, then save them in another table (say All_category_table) then do a join as shown below:
SELECT A.category, count(*) total FROM
(SELECT Category FROM All_category_table) A
LEFT JOIN items B
ON A.Category=B.Category
GROUP BY B.Category;
This answer is applicable for when you do not have another table holding the possible category values.
Let's say you have a table called real_table with a not null & value constrained column category. In this column you know you can theoretically encounter 5 different values: 'CATEGORY_0', 'CATEGORY_1', 'CATEGORY_2', 'CATEGORY_3', 'CATEGORY_4':
CREATE TABLE real_table
(
id VARCHAR(255) NOT NULL
PRIMARY KEY,
category VARCHAR(255) NOT NULL
CONSTRAINT category_in CHECK (
category in ('CATEGORY_0',
'CATEGORY_1',
'CATEGORY_2',
'CATEGORY_3',
'CATEGORY_4')
)
);
But your actual data set in the table does not include any row with value 'CATEGORY_0'. So when you run a query such as:
SELECT real_table.category AS category, COUNT(*) AS cnt
FROM real_table
GROUP BY real_table.category;
you will see, that you get result like this:
category
cnt
CATEGORY_1
150
CATEGORY_2
20
CATEGORY_3
12
CATEGORY_4
1
Hmm, the 'CATEGORY_0' is omitted. Not good.
Since your categories are not backed by another table, then you must create an artificial dataset of the possible categories that looks as below:
SELECT 'CATEGORY_0' AS category_entry
UNION ALL
SELECT 'CATEGORY_1' AS category_entry
UNION ALL
SELECT 'CATEGORY_2' AS category_entry
UNION ALL
SELECT 'CATEGORY_3' AS category_entry
UNION ALL
SELECT 'CATEGORY_4' AS category_entry;
You can use this in your original query as a table to do a right join on:
SELECT all_categories.category_entry AS category,
COUNT(real_table.id) AS cnt -- important to count some non-null value, such as PK of the real_table
FROM real_table
RIGHT JOIN
(SELECT 'CATEGORY_0' AS category_entry -- not present in any row in table 'all_categories'
UNION ALL
SELECT 'CATEGORY_1' AS category_entry
UNION ALL
SELECT 'CATEGORY_2' AS category_entry
UNION ALL
SELECT 'CATEGORY_3' AS category_entry
UNION ALL
SELECT 'CATEGORY_4' AS category_entry) all_categories
ON real_table.category = all_categories.category_entry
GROUP BY all_categories.category_entry;
Now when you run the query, you should get the desired output:
category
cnt
CATEGORY_0
0
CATEGORY_1
150
CATEGORY_2
20
CATEGORY_3
12
CATEGORY_4
1
The 'CATEGORY_0' is now included with zero cnt. Nice.
Now let's say that the category column is not not null constrained and can also possibly include some other unexpected category values (e.g. 'CATEGORY_66'):
CREATE TABLE real_table
(
id VARCHAR(255) NOT NULL
PRIMARY KEY,
category VARCHAR(255) -- nullable and no constraint for valid values
);
We would like to include these null and unexpected category counts in the result set as well.
Then we must prepare the artificial dataset of the possible categories differently:
SELECT DISTINCT all_categories.category_entry
FROM (SELECT 'CATEGORY_0' AS category_entry -- not present in any row in table 'all_categories'
UNION ALL
SELECT 'CATEGORY_1' AS category_entry
UNION ALL
SELECT 'CATEGORY_2' AS category_entry
UNION ALL
SELECT 'CATEGORY_3' AS category_entry
UNION ALL
SELECT 'CATEGORY_4' AS category_entry
UNION ALL
SELECT DISTINCT category
FROM real_table AS category_entry) all_categories;
and use it as before:
SELECT distinct_categories.category_entry AS category,
COUNT(real_table.id) AS cnt -- important to count some non-null value, such as PK of the real_table
FROM real_table
RIGHT JOIN
(SELECT DISTINCT all_categories.category_entry
FROM (SELECT 'CATEGORY_0' AS category_entry -- not present in any row in table 'all_categories'
UNION ALL
SELECT 'CATEGORY_1' AS category_entry
UNION ALL
SELECT 'CATEGORY_2' AS category_entry
UNION ALL
SELECT 'CATEGORY_3' AS category_entry
UNION ALL
SELECT 'CATEGORY_4' AS category_entry
UNION ALL
SELECT DISTINCT category
FROM real_table AS category_entry) all_categories) distinct_categories
ON real_table.category = distinct_categories.category_entry
GROUP BY distinct_categories.category_entry;
Now when you run the query, the output should also include counts for additional categories and null categories
category
cnt
CATEGORY_0
0
CATEGORY_1
150
CATEGORY_2
20
CATEGORY_3
12
CATEGORY_4
1
CATEGORY_66
13
10
Both unexpected 'CATEGORY_66' (with 13 entries) as well as null category (with 10 entries) are now included in the result set
I cannot vouch for the performance of the provided queries - somebody more experienced might weigh in on that?

mysql find numbers in query that are NOT in table

Is there a simple way to compare a list of numbers in my query to a column in a table to return the ones that are NOT in the db?
I have a comma separated list of numbers (1,57, 888, 99, 76, 490, etc etc) that I need to compare to the number column in a table in my DB. SOME of those numbers are in the table, some are not. I need the query to return those that are in my comma separated list, but are NOT in the DB...
I would put the list of numbers to be checked in a table of their own, then use WHERE NOT EXISTS to check whether they exist in the table to be queried. See this SQLFiddle demo for an example of how this might be accomplished:
If you're comfortable with this syntax, you can even avoid putting into a temp table:
SELECT * FROM (
SELECT 1 AS mycolumn
UNION
SELECT 2
UNION
SELECT 3
UNION
SELECT 4
UNION
SELECT 5
UNION
SELECT 6
UNION
SELECT 7
) a
WHERE NOT EXISTS ( SELECT 1 FROM mytable b
WHERE b.mycolumn = a.mycolumn )
UPDATE per comments from OP
If you can insert your very long list of numbers into a table, then query as follows to get the numbers that are not found in the other table:
SELECT mynumber
FROM mytableof37000numbers a
WHERE NOT EXISTS ( SELECT 1 FROM myothertable b
WHERE b.othernumber = a.mynumber)
Alternately
SELECT mynumber
FROM mytableof37000numbers a
WHERE a.mynumber NOT IN ( SELECT b.othernumber FROM myothertable b )
Hope this helps.
May be this is what you are looking for.
Convert your CSV to rows using SUBSTRING_INDEX. Use NOT IN operator to find the values which is not present in DB
Then Convert the result back to CSV using Group_Concat.
select group_concat(value) from(
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(t.a, ',', n.n), ',', -1) value
FROM csv t CROSS JOIN
(
SELECT a.N + b.N * 10 + 1 n
FROM
(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
ORDER BY n
) n
WHERE n.n <= 1 + (LENGTH(t.a) - LENGTH(REPLACE(t.a, ',', '')))) ou
where value not in (select a from db)
SQLFIDDLE DEMO
CSV TO ROWS referred from this ANSWER
You could use the 'IN' clause of MySQL. Maybe check this out IN clause tutorial

Search for the existance of many objects in a database

Say I have a database with 5 million users, with the columns
id (unsigned int, auto-increment), facebook_id (unsigned int), and name (varchar)
In a program, I have a list of a variable amount of users from a person's facebook friend list (generally ranging from 500-1200 different facebook ids).
What's the most efficient way to send a query to my database that returns the facebook_id's of all of the users where that same facebook_id exists in the database?
Pseudo-code:
$friends = array(12345, 22345, 32345, 42345, 52345, ... ~1000 more);
$q = mysql_query("SELECT * FROM users ...");
$friendsAlreadyUsingApp = parseQuery($q);
This is a topic of almost an endless number of articles, blogs, Q&As etc; and the essence of this problem is that it looks really simple - but isn't.
The heart of the problem is that the parameters looks like it should work using WHERE field IN() BUT it does not do that because the parameter is a single string that just happens to have lots of commas in it.
So, when that parameter is passed to SQL it is necessary to process that single string into multiple parts so that the field can be compared to each part. This is where it gets a little complex as not all database types have all the same features to handle this. MySQL for example does not have a table variable that MS SQL Server provides.
So. A simple method, for MySQL is this:
SET #param := '105,110,125,135,145,155,165,175,185,195,205';
SELECT
*
FROM Users
WHERE FIND_IN_SET(facebook_id, #param) > 0
;
FIND_IN_SET Return the index position of the first argument
within the second argument
Just how well this scales in your database I cannot tell, it might not be acceptable for parameters containing 1000+ id's.
So if text processing like FIND_IN_SET is too slow, then each id needs to be broken out from the parameter and inserted into a table. That way the resulting table can be used through an INNER JOIN to filter the users; but this requires a table and inserts which take time, and there may be concurrency issues if more than one user is attempting to use that table at the same time.
Using the following sets-up a table of 10,000 integers (1 to 10,000)
/* Create a table called Numbers */
CREATE TABLE `Numbers`
(
`Number` int PRIMARY KEY
);
/* use cross joins to create 10,000 integers from 1 & store into table */
INSERT INTO Numbers (Number)
select 1 + (a.a + (10 * b.a) + (100 * c.a) + (1000 * d.a)) as N
from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as d
;
This "utility table" can then be used to divide a comma separated parameter into a derived table of the individual integers, and this then used in an INNER JOIN to your users table will provide the wanted result.
SET #param := '105,110,125,135,145,155,165,175,185,195,205';
SET #delimit := ',';
SELECT
users.id
, users.facebook_id
, users.name
FROM users
INNER JOIN (
SELECT
CAST(SUBSTRING(iq.param, n.number + 1, LOCATE(#delimit, iq.param, n.number + 1) - n.number - 1) AS UNSIGNED INTEGER) AS itemID
FROM (
SELECT
concat(#delimit, #param, #delimit) AS param
) AS iq
INNER JOIN Numbers n
ON n.Number < LENGTH(iq.param)
WHERE SUBSTRING(iq.param, n.number, 1) = #delimit
) AS derived
ON users.facebook_id = derived.itemID
;
This query can be used as the basis for a stored procedure which might be easier for you to call from PHP.
See this SQLFiddle demo

return blank row when no records sql server

I have a table tblAccount. I want to get the top 4 rows from the table. If no record is there, I want to get 4 blank rows.
select *
from tblAccount
o/p
----
AccountID AccountNo
1 #101
2 #102
NULL NULL
NULL NULL
The above should be the result if two records are there.
SQLFiddle demo
select TOP 4 AccountID,AccountNo
from
(
select 0 as srt,AccountID,AccountNo from tblAccount
union all
select 1 as srt,NULL as AccountID, NULL as AccountNo
union all
select 2 as srt,NULL as AccountID, NULL as AccountNo
union all
select 3 as srt,NULL as AccountID, NULL as AccountNo
union all
select 4 as srt,NULL as AccountID, NULL as AccountNo
) as t
order by srt,AccountID
This should work. You could do the same thing with a temp table, just give it the right number of fields and rows.
with meganull(a,b) as (
select CAST(null as int),
CAST(null as varchar(max))
union all
select *
from meganull
)
select top 4 *
from (
select *
from tblAccount
union all
select *
from meganull) as sq
try this...
Select * FROM (VALUES (1),(2),(3),(4)) AS value(tmpID) left join
(
select Row_Number() over (order by AccountID) as RowCtr, *
from tblAccount
) accountTable on tmpID = accountTable.RowCtr
I used a similar technique when I wanted a way to force a certain number of rows to display in a SSRS report, where the blank rows represented empty spots in a physical rack.