I want to display the result of my MySQL query by ordering them as they are listed in the where clause. Currently, the results are not listed in the order of the numbers in my list.
Here is my statement
SELECT *
FROM subscription
WHERE phone in
(
'255769016082',
'255742594724',
'255753299742',
'255759502732',
'255753839708'
)
Since you want to order by multiple values in a non-sequential order, that is they aren't numerically in order nor would they be ordered correctly in order as a VARCHAR, you need to apply numeric values to them. Here is how you can do that.
if object_id('tempdb..#temp') is not null drop table #temp
create table #temp (phone varchar(20))
insert into #temp (phone) values
('255769016082'),
('255742594724'),
('255753299742'),
('255759502732'),
('255753839708'),
('257538312333')
SELECT *
FROM #temp
WHERE phone in
(
'255769016082',
'255742594724',
'255753299742',
'255759502732',
'255753839708'
)
ORDER BY
CASE
WHEN phone = '255769016082' THEN 1
WHEN phone = '255742594724' THEN 2
WHEN phone = '255753299742' THEN 3
WHEN phone = '255759502732' THEN 4
WHEN phone = '255753839708' THEN 5
END
In the future, if you are sorting on non-numeric fields, you need to be familiar how SQL Server handles this.
Consider this
if object_id('tempdb..#char') is not null drop table #char
create table #char(stringField varchar(6))
insert into #char (stringField) values
('a'),
('A'),
('b'),
('B'),
('AB'),
('aB'),
('ab'),
('Ab'),
('ba'),
('Ba'),
('bA'),
('BA')
select * from #char order by stringField asc
select * from #char order by stringField desc
Related
I have a lot of different tables in my database, and I need somehow to get last inserted rows from those tables. Like social networks feeds. Also, those tables are have not random, but unknown names, because they all generated by users.
In example:
I have tables: A,B,C and D with 5k rows in each table.
I need somehow to get last rows from those tables and make it ordered by id, like we do in a simple query: "SELECT * FROM table A ORDER BY id DESC", but I'm looking for something like: "SELECT * FROM A,B,C,D ORDER BY id DESC".
Tables have same structure.
You can use union and order by if your tables have the same structure. Something like:
select *
from (
select * from A
union all
select * from B
union all
select * from C
) order by id desc
If the tables don't have the same structure then you cannot select * from all and order them and you might want to do two queries. First would be:
select id, tableName
from (
select id, 'tableA' as tableName from A
union all
select id, 'tableB' as tableName from B
union all
select id, 'tableC' as tableName from C
) order by id desc
Which will give you the last IDs and the tables where they are inserted. And then you need to get the rows from each respective table.
With pure Mysql it will be a bit hard. You can select the table names like:
SELECT table_name FROM information_schema.tables; but still how to use them in the statement? You will need to generate it dynamically
A procedure to generate the query dynamically can be something like ( I haven't tested it but I believe with some debugging it should work) :
DELIMITER $$
CREATE PROCEDURE buildQuery (OUT v_query VARCHAR)
BEGIN
DECLARE v_finished INTEGER DEFAULT 0;
DECLARE v_table_count INTEGER DEFAULT 0;
DECLARE v_table varchar(100) DEFAULT "";
-- declare cursor for tables (this is for all tables but can be changed)
DEClARE table_cursor CURSOR FOR
SELECT table_name FROM information_schema.tables;
-- declare NOT FOUND handler
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET v_finished = 1;
OPEN table_cursor;
SET v_query="select * from ( ";
get_table: LOOP
FETCH table_cursor INTO v_table;
SET v_table_count = v_table_count + 1;
IF v_finished = 1 THEN
LEAVE get_table;
END IF;
if v_table_count>1 THEN
CONCAT(vquery, " UNION ALL ")
END IF;
SET v_query = CONCAT(vquery," select * from ", v_table );
END LOOP get_table;
SET v_query = CONCAT(vquery," ) order by id desc " );
-- here v_query should be the created query with UNION_ALL
CLOSE table_cursor;
SELECT #v_query;
END$$
DELIMITER ;
If each table's id is counted seperatly you can't order by ID, so you'll need to calculate a global id and use it on all of your tables.
You can do it as follows:
Assuming you have 2 tables A,B:
Create Table A(id int NOT NULL auto_increment, name varchar(max), value varchar(max), PRIMARY_KEY(id));
Create Table B(id int NOT NULL auto_increment, name varchar(max), value varchar(max), PRIMARY_KEY(id));
Add another table IDS with id as auto increment primary key.
Create table IDS (id int NOT NULL auto_increment, ts Timestamp default CURRENT_TIMESTAMP, PRIMARY_KEY(id));
For all your tables id column should use now the id from the IDS table as foreign key instead of auto increment.
Create Table A(id int NOT NULL auto_increment, name varchar(max), value varchar(max), PRIMARY_KEY(id),CONSTRAINT fk_A_id FOREIGN KEY(id) REFERENCE IDS(id) ON DELETE CASCADE ON UPDATE CASCADE);
Create Table B(id int NOT NULL auto_increment, name varchar(max), value varchar(max), PRIMARY_KEY(id),CONSTRAINT fk_A_id FOREIGN KEY(id) REFERENCE IDS(id) ON DELETE CASCADE ON UPDATE CASCADE);
for each table add before insert trigger, the trigger should first insert row to the IDS table and insert the LAST_INSERT_ID the table.
Create TRIGGER befor_insert_A BEFORE INSERT On A
FOR EACH ROW
BEGIN
insert into IDS() values ();
set new.id = LAST_INSERT_ID();
END
Create TRIGGER befor_insert_B BEFORE INSERT On B
FOR EACH ROW
BEGIN
insert into IDS() values ();
set new.id = LAST_INSERT_ID();
END
Now you can create view from all tables with union all, the rows of v can be sorted now by the id and give the cronlogic order of insertion.
Create view V AS select * from A UNION ALL select * from B
For example you can query on V the latest 10 ids:
select * from V Order by id desc LIMIT 10
Other option is to add timestamp for each table and sort the view by the timestamp.
Hi are you looking for this? However the id is not a good column to see the last updated among different tables.
select *
from A
join B
on 1=1
join C
on 1=1
join D
on 1=1
order by A.id desc
How do I insert a sql row into a new table where it meets criteria but resets the id value. In other words, copy the row, but reset the id value.
This is my current sql
INSERT INTO followers_lost SELECT * FROM followers WHERE pk = $pk
I tried to SET id=null and VALUE (0), but both don't work.
All you have to do since you want all the columns except the identity is specify all the non-identity columns on the insert:
INSERT INTO [followers_lost] ([Column1],[column2]...{but not the identity
column})
SELECT [Column1],[column2]...{but not the identity column} FROM followers WHERE
pk = $pk
You can create the column and then update it:
SET #new_id=0;
UPDATE your_table
SET id = #new_id := #new_id + 1
where id = 0
OK based on your comment I think you are trying to take all or some of the fields from Followers except the PK and put them into Followers_Lost where they equal a certain PK. If you want multiple PK's you would need to change the where clause to an IN statement instead of an equal and adjust your values accordingly.
CREATE TABLE dbo.UAT_Followers_Lost (PK INT IDENTITY(1,1),DATA VARCHAR(50) )
CREATE TABLE dbo.UAT_Followers (PK INT IDENTITY(1,1),DATA VARCHAR(50) )
INSERT INTO dbo.UAT_Followers
(DATA)
SELECT 'Jan'
UNION ALL
SELECT 'Feb'
UNION ALL
SELECT 'Mar'
DECLARE #PK INT
SET #PK = 1
INSERT INTO dbo.UAT_Followers_Lost
(Data)
SELECT Data
FROM dbo.UAT_Followers
WHERE PK = #PK
I am creating empty temporary table based on another table in my db and adding an extra column (PRICE) which i am trying to populate from query,
SELECT TOP 0 ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS RowNumber,
ID,
NULL AS PRICE
INTO #TMP_TABLE
FROM SQL_TABLE
when i fill this table as INSERT INTO #TMP_TABLE ... the value i am getting in PRICE column is either 0 or 1, but when i execute query seperately, i am getting decimal values (like0.0634).
how can i store decimal values in temp table above ? or is there any other way to create empty temp table ?
Use CREATE TABLE and define explicitly columns types:
CREATE TABLE #TMP_TABLE(RowNumber INT, ID <you_type>, Price <your_type>)
Default for NULL is INT, check:
SELECT x = NULL INTO #x;
EXEC tempdb..sp_columns '#x';
So your fraction are converted implicitly to INT
One good rule for future EXPLICIT IS ALWAYS BETTER THAN IMPLICIT
you either create the table with a create table statement:
create table #TMP_TABLE
( RowNumber int
, ID <whatever datatype>
, PRICE numeric(10,2)
);
or if you insist on select into declare the datatype :
SELECT TOP 0 ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS RowNumber,
ID,
cast(NULL as numeric(10,2)) AS PRICE
INTO #TMP_TABLE
FROM SQL_TABLE
Okay here is the situation:
I the following data in a table.
PAIR_NO NO NO2
3 5678EFGH 1234ABCD
4 1111BBBB 0000AAAA
1 1234ABCD 5678EFGH
2 0000AAAA 1111BBBB
The constraints are if no = no2 in another row skip that row.
So in this sample data the only rows that would be selected should be pair no 3 and 4.
I have tried to merge and inner join with self but I just keep getting all 4 rows back.
I have tried to insert into a table where not exists but again I get 4 rows inserted.
SELECT a.* from PAIRS a
inner join PAIRS b on a.no=b.no2 and a.no2=b.no;
I was thinking maybe selecting distinct number from column 1 and then check those in column 2 but I think that would yield the same four rows.
I may be over thinking this problem and maybe some here can look at this and see where the solution is hiding.
I am currently testing this on MySQL but it should run on SQLServer 2008. I have searched but all the questions didn't seem to match my data set issue.
Taking you at your word, meaning selecting all records where the value of no column does not appear anywhere in no2 column in the same table, try this:
SELECT A.PAIR_NO, A.NO, A.NO2
FROM PAIRS A
LEFT JOIN PAIRS B ON(A.NO = B.NO2)
WHERE B.PAIR_NO IS NULL -- assuming this column is not nullable
Another option is to use NOT EXISTS:
SELECT PAIR_NO, NO, NO2
FROM PAIRS A
WHERE NOT EXISTS(
SELECT 1
FROM PAIRS B
WHERE B.NO2 = A.NO
)
I personally prefer the LEFT JOIN option since it's shorter and more readable.
Both of these statement should work on both MySql and Sql Server.
Okay fellas I want to thank you all for helping, but I think I solved my issue. Took me a second but I believe this is what I am after (SQL Server 2008):
if OBJECT_ID('tempdb..#pairs') is not null drop table #pairs
if OBJECT_ID('tempdb..#pairs_final') is not null drop table #pairs_final
create table #pairs(pair_no int, a_no varchar(17),a_no2 varchar(17))
create table #pairs_final(pair_no int Identity(1,1), a_no varchar(17),a_no2 varchar(17))
insert into #PAIRS values(1,'1234ABCD','5678EFGH');
insert into #PAIRS values(1,'1234ABCD','XXXX9999');
insert into #PAIRS values(2,'0000AAAA','1111BBBB');
insert into #PAIRS values(3,'5678EFGH','1234ABCD');
insert into #PAIRS values(4,'1111BBBB','0000AAAA');
insert into #PAIRS values(1,'XXXX9999','1234ABCD');
insert into #pairs_final
select a.a_no,a.a_no2 from #pairs a
join (
select distinct a_no_p from(
select pair_no,a_no_p,
ROW_NUMBER() over (partition by pair_no order by a_no_p) as RN
from #pairs
unpivot(
a_no_p for clms in (a_no2,a_no)
) as umpvt
) as mypairs
where RN = 1
) as my_pairs on my_pairs.a_no_p=a.a_no
select * from #pairs_final
This will give me the following results:
pair_no a_no a_no2
1 1234ABCD 5678EFGH
2 1234ABCD XXXX9999
3 0000AAAA 1111BBBB
Hope this might help someone else.
Enjoy.
DECLARE #TBL AS TABLE
(
[NO] INT,
[CODE] VARCHAR(50),
[AREA] VARCHAR(50)
)
/* EXAMPLE 1 */
INSERT INTO #TBL([NO],[CODE],[AREA]) VALUES (1,'001','A00')
INSERT INTO #TBL([NO],[CODE],[AREA]) VALUES (2,'001','A00')
INSERT INTO #TBL([NO],[CODE],[AREA]) VALUES (3,'001','B00')
INSERT INTO #TBL([NO],[CODE],[AREA]) VALUES (4,'001','C00')
INSERT INTO #TBL([NO],[CODE],[AREA]) VALUES (5,'001','C00')
INSERT INTO #TBL([NO],[CODE],[AREA]) VALUES (6,'001','A00')
INSERT INTO #TBL([NO],[CODE],[AREA]) VALUES (7,'001','A00')
/* EXAMPLE 2 */
/* ***** USE THIS CODE TO ENTER DATA FROM DIRECT TABLE *****
SELECT
ROW_NUMBER() OVER(ORDER BY [FIELD_DATE]) AS [NO]
,[FIELD_CODE] AS [CODE]
,[FIELD_AREA] AS [AREA]
FROM TABLE_A
WHERE CAST([FIELD_DATE] AS DATE) >= CAST('20200307' AS DATE)
ORDER BY [FIELD_DATE],[FIELD_CODE]
*/
SELECT
A.NO AS ANO
,A.CODE AS ACODE
,A.AREA AS AAREA
,B.NO AS BNO
,B.CODE AS BCODE
,B.AREA AS BAREA
,CASE WHEN A.AREA=B.AREA THEN 'EQUAL' ELSE 'NOT EQUAL' END AS [COMPARE AREA]
FROM #TBL A
LEFT JOIN #TBL B
ON A.NO=B.NO+1
I run the following query
CREATE TABLE #Temp
(
Data VARCHAR(100)
)
INSERT INTO #Temp VALUES ('241.110')
INSERT INTO #Temp VALUES ('1340.306')
SELECT * FROM #Temp ORDER BY Data asc
Result is
1340.306
241.110
When I sort same data in excel with order as Smallest to Largest, it has
241.110
1340.306
In SQL Server i need the same ordering as in excel. What am I doing wrong?
If you have mixed numerics and text in one column you could use this to sort on numeric values for the numerics.
CREATE TABLE #Temp
(
Data varchar(100)
)
INSERT INTO #Temp VALUES ('241.110')
INSERT INTO #Temp VALUES ('1340.306')
INSERT INTO #Temp VALUES ('b')
INSERT INTO #Temp VALUES ('aa')
INSERT INTO #Temp VALUES ('241.2')
SELECT *
FROM #Temp
ORDER BY
case isnumeric(Data) when 0 then Data end asc,
case isnumeric(Data) when 1 then cast(Data as numeric(10,3)) end asc
Result:
Data
----------
241.110
241.2
1340.306
aa
b
Edit 1 A second column to be treated the same way.
SELECT *
FROM #Temp
ORDER BY
case isnumeric(Data) when 0 then Data end asc,
case isnumeric(Data) when 1 then cast(Data as numeric(10,3))end asc,
case isnumeric(Data2) when 0 then Data2 end asc,
case isnumeric(Data2) when 1 then cast(Data2 as numeric(10,3))end asc
The sort in sql-server is in alphabetical order and '1' comes before '2'.
To get the same sort as excel, I suggest you use a numeric field instead of VARCHAR.