Tables with dynamic names as fields - mysql

I have a table which contains a field that when we add a letter to it it becomes a table name, so far i can only fetch all from the first table and then do each table_name at once. So i'm looking for a way to all of the above in one query.
Queries
select table_name from main
select date,data from X$table_name order by date desc limit 1
main
table_name name
000001 X1
000002 X2
000003 X3
000004 X4
000005 X5
Table X000001
id date data
5 2016-12-05 data_02_05
4 2016-12-04 data_02_04
3 2016-12-03 data_02_03
2 2016-12-02 data_02_02
1 2016-12-01 data_02_01
Table X000002
id date data
5 2016-12-05 data_02_05
4 2016-12-04 data_02_04
3 2016-12-03 data_02_03
2 2016-12-02 data_02_02
1 2016-12-01 data_02_01
Expected result
table_name date data
000001 2016-12-05 data_01_05
000002 2016-12-05 data_02_05
000003 2016-12-05 data_03_05
000004 2016-12-05 data_04_05
000005 2016-12-05 data_05_05

you need to use a dynamic query or prepared statement for that purpose.
declare #tab_name varchar(100);
set #tab_name := (select table_name from main);
SET #t1 := CONCAT("select `date`,data from X",#tab_name," order by `date` desc limit 1");
PREPARE stmt3 FROM #t1;
EXECUTE stmt3;
DEALLOCATE PREPARE stmt3;

Related

Retrieve last row with specific condition

Suppose we have a table like:
ID
Account
Amount
Date
1
4455
52
01-01-2022
2
4455
32
02-01-2022
3
4455
23
03-01-2022
4
4455
23
04-01-2022
5
6565
236
01-01-2022
6
6565
623
02-01-2022
7
6565
132
03-01-2022
8
2656
564
01-01-2022
9
2656
132
02-01-2022
We need to retrieve every last row of given account_no. We need output like:
ID
Account
Amount
Date
4
4455
23
04-01-2022
7
6565
132
03-01-2022
10
2656
13
03-01-2022
Kindly suggest me a query to retrieve data like this in table of 2000 records.
You want the last row of certain query. So you must be having an order by clause. Just reverse the ordering and use a limit clause with limit set to one row.
SELECT column_name(s)
FROM table_name
WHERE condition
order by your_reversed_orderby_clause
LIMIT 1;
If you are using MySQL 8, then you can use ROW_NUMBER() function for this:
WITH CTE AS
(
SELECT ID,Account,Amount,Date
,ROW_NUMBER() OVER(PARTITION BY Account ORDER BY ID DESC) AS RN
FROM Table1
)
SELECT * FROM CTE
WHERE RN=1
ORDER BY ID;
ID
Account
Amount
Date
RN
4
4455
23
2022-04-01 00:00:00
1
7
6565
132
2022-03-01 00:00:00
1
9
2656
132
2022-02-01 00:00:00
1
See this db<>fiddle
SELECT * FROM table_name
WHERE ID IN (
SELECT max(ID) FROM table_name
GROUP BY Acount
ORDER BY Account
)

How to count rows by date in mysql and show dynamic headers

I need to show count of each sources(type colum) and show according to date range
Currently my data is as following
id type date
11 air 2019-10-21 10:00:01
21 air 2019-10-21 10:00:02
31 air 2019-10-21 10:01:03
41 air 2019-10-21 11:01:03
51 air 2019-10-21 12:01:03
61 water 2019-10-21 12:01:03
71 water 2019-10-21 15:01:04
81 water 2019-10-22 16:01:03
81 sea 2019-10-22 16:01:03
81 sea 2019-10-24 16:01:03
I want to achive output like the following
type 2019-10-21 | 2019-10-22
air 5 0
water 2 1
sea 0 1
and also give range in between 2019-10-21 and 2019-10-21
i have tried this query
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'count(case when type = ',
'type',
' then type else null end) AS ''',
date(date), ''''
)
) INTO #sql
FROM content where date(`date`) between '2021-02-08' AND '2021-02-10';
SET #sql = CONCAT('SELECT type, ', #sql, '
FROM content
GROUP BY type limit 2');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
but it give wrong results and counts the total
type 2021-02-08 2021-02-09 2021-02-10
sea 3 3 3
air 5316 5316 5316

Subtract two rows' values within the same column using Mysql group by ID

I have a table as shown below. I want to do a partition and then subtract the values in the same column to get the difference.
Since there is no partition or equivalent function available in MySQL,
can anyone give me an idea of how to do it?
I have worked out the partition but not the other part.
SELECT ID,Date,
#row_number:=CASE WHEN #ID=ID THEN #row_number+1 ELSE 1 END AS row_number,
#ID:=ID AS ID,value
FROM table1, (SELECT #row_number:=0,#ID:='') AS t
ORDER BY id,Date;
Input:
ID Date Value
1001 24-07-2017 09:43 10
1002 24-07-2017 09:43 11
1003 22-08-2017 21:42 10
1001 07-09-2017 20:33 11
1003 07-09-2017 20:33 44
1002 24-07-2017 09:43 55
1004 07-09-2017 20:33 66
Output should be:
rowno ID Date Value Diff
1 1001 24-07-2017 09:43 10 N/A
2 1001 07-09-2017 20:33 11 1
1 1002 24-07-2017 09:43 11 N/A
2 1002 24-07-2017 09:43 55 44
1 1003 22-08-2017 21:42 10 n/A
2 1003 07-09-2017 20:33 44 34
1 1004 07-09-2017 20:33 66 N/A
Your dates are incorrect. When you order by this column, you order by day first. Proper ordering is year-month-day. Use the proper datatype, datetime or timestamp. To do this you can do the following:
alter table table1 add column d datetime;
update table1 set d = str_to_date(`Date`, '%d-%m-%Y %H:%i');
alter table table1 drop column `Date`;
The query to get your desired result is then:
SELECT ID, d, Value,
IF(#ID=ID, Value - #prevV, 'N/A') AS diff,
#row_number:=CASE WHEN #ID=ID THEN #row_number+1 ELSE 1 END AS row_number,
#prevV := Value,
#ID:=ID AS ID
FROM table1
, (SELECT #row_number:=0, #ID:='', #prevV := NULL) AS t
ORDER BY id, d;
All you have to do is add another variable to hold the value of the previous row.
see it working live in an sqlfiddle
here's another sqlfiddle to showcase what happens when you have 3 rows per ID

merging tables by using PROC SQL where in statement in SAS

everyone.
I'm currently using SAS.
Here's my situation.
I have a table called 'a', which looks like:
id_c id_t
5 3
2 9
15 1
65 43
... ...
This,a, table has only two different ids from other tables. These 5&3, 2&9,... are pairs.
What I want to do is that I want to take out each id_t and id_c so that I can merge other variables in other tables, respectively.
To do so, first I decide to take out id_t and merge other variables.
This following code works:
proc sql;
create table t1 as
select *
from other_var_table_1
where id_t in (select id_t from a);
quit;
The result is:
id_t var1 var2 var3
3
9
1
43
Here, the order of id_t is exactly the same as the order of id_t in table 'a'.
However, when I do the same thing by using id_c, the order is messed up.
I want:
id_c var_x var_y var_z
5
2
15
65
but when I run the same code, the result becomes such as:
proc sql;
create table t2 as
select *
from other_var_table_2
where id_c in (select id_c from a);
quit;
id_c var_x var_y var_z
65
15
5
2
The purpose of doing this is to merge the two tables again including all the variables such as:
data final;
set t2;
set t1;
run;
id_c var_x var_y var_z id_t var1 var2 var3
5 3
2 9
15 1
65 43
... ...
It would be greatly appreciated if someone could help me out.
Thank you,
/****CREATING DATASETS****/
data a;
input int_c int_t;
cards;
5 3
2 9
15 1
65 43
;
run;
/*Create a **seq** number so that your order does not change*/
data a;
set a;
seq = _n_;
run;
data other_var_table_1;
input int_t var1 var2 var3;
cards;
3 12 43 76
1 10 20 30
;
run;
data other_var_table_2;
input int_c var_x var_y var_z;
cards;
2 100 200 300
5 1 2 3
65 10 20 30
;
run;
/****JOINING THE REQUIRED COLUMNS****/
proc sql;
create table final as
select r.*,p.var1,p.var2,p.var3,q.var_x,q.var_y,q.var_z
from
a r
left join
other_var_table_1 p
on r.int_t = p.int_t
left join
other_var_table_2 q
on r.int_c = q.int_c
order by r.seq;
run;
You can drop column seq after the results if you want. Let me know if you have any doubts.
My Output:
int_c |int_t |SEQ |var1 |var2 |var3 |var_x |var_y |var_z
5 |3 |1 |12 |43 |76 |1 |2 |3
2 |9 |2 |. |. |. |100 |200 |300
15 |1 |3 |10 |20 |30 |. |. |.
65 |43 |4 |. |. |. |10 |20 |30

how can I add a new column which counts the number of rows as serial number

record of
id fare commission routecode vehicle number productcode date time driver owner name
15 12345 123 4533 1 3344 2011-03-18 00:00:00 yasir saleem
20 a a 3433 1 2333 2011-03-25 00:00:00 yasir saleem
36 11111 11111 3433 1 2333 2011-03-25 16:13:12 yasir saleem
9 1233 123 3433 nk-234 2333 2011-03-24 00:00:00 siddiq aslam
21 1200 120 4533 nk-234 7655 2011-03-24 00:00:00 siddiq aslam
22 1200 133333 0987 nk-234 2333 2011-03-11 00:00:00 siddiq aslam
23 10000 11 4533 nk-234 7655 2011-03-19 00:00:00 siddiq aslam
25 122 12 0987 nk-234 2333 2011-03-11 00:00:00 siddiq aslam
26 1000 100 3344 nk-234 7655 2011-03-11 00:00:00 siddiq aslam
27 1000 100 3344 nk-234 2333 2011-03-10 00:00:00 siddiq aslam
34 100 10 3344 nk-234 2333 2011-03-18 00:00:00 siddiq aslam
35 100 10 3344 nk-234 2333 2011-03-02 00:00:00 siddiq aslam
5 1000 100 1234 wq1233 3344 2011-03-10 22:30:00 waqas sami
6 2222 22 1234 wq1233 3344 2011-03-17 22:30:00 waqas sami
24 a a 4533 PSS-1234 7655 2011-03-02 00:00:00 salman salam
42633 145175
I want to add another column before id which counts the number of
rows. It should start from 1 and increment by 1 for each row.
If you mean in a SELECT statement:
Say your select was
select * from tbl
It becomes
select #n := #n + 1 RowNumber, t.*
from (select #n:=0) initvars, tbl t
Notes:
select #n:=0 is used to reset the global variable to 0
#n := #n + 1 increases it by 1 for each row, starting from 1. This column is named "RowNumber"
Add a new column mySerial to the table myTable and increment each row by 1 (starting at '1'):
ALTER TABLE myTable ADD mySerial int(11) DEFAULT '0' NOT NULL;
SELECT #n:=0;
UPDATE myTable SET mySerial = #n := #n + 1;
So, you want to add a column to every row with the rowcount in it? It's not possible to do that automatically, but you can add a column and update it on every insert (UPDATE table SET (rowcount = SELECT COUNT(*) FROM TABLE)) but I wonder why you want to do that? It seems to me you want to workaround something and I think there must be a better solution than adding a rowcount column.
I am not sure if i understand your question completely, but to add a column infront of id run this query
ALTER TABLE `yourtablename` ADD `yournewfield` VARCHAR( 50 ) NOT NULL BEFORE `id`
You may want to look into this blog post: http://jimlife.wordpress.com/2008/09/09/displaying-row-number-rownum-in-mysql/
Seems to have a solution for adding a row number to a query result, which might solve your problem.