create table su AS select don't work - mysql

i have this table
ID |user |Contact |Duration
1 asif 11 00
2 bob 22 65
3 cena 33 00
4 asif 44 00
5 cena 33 00
6 cena 33 00
7 bob 55 43
8 asif 44 33
9 bob 66 00
i want use this sql;
CREATE TABLE su
AS (select user,
contactcount,
duration,
case when durationcount = 0 then 0 else duration/durationcount end
from (
select user,
count(distinct contact) contactcount,
sum(duration) duration,
sum(case when duration > 0 then 1 else 0 end) durationcount
from table4
group by user
) t)
But phpmyadmin, give error. #1166 - Incorrect column name 'case when durationcount = 0 then 0 else duration/durationcount end'
expected ouput;
|user |count |duration_total |case when durationcount = 0 then 0 else duration/durationcount end
asif 2 33 33
bob 3 108 54
cena 1 00 00
what is wromg in this sql ?
the goal is to create new table whit ID, user, total duration per user and average time by user when duration >0

Related

Month-end and weekend logic

Pull the data month end and weekend without weekends.if get the weekend then retrieve the before that weekend.
Ex:the date is 20 or 21 Of AUGUST(WEEKENDS),Then i need the 19th(WEEKDAY) data..
O r a c l e
You could use CASE expression with To_Char(Date_column, 'd').
The WITH clause is here just to generate some sample data and, as such, it is not a part of the answer.
Here is the answer including the order number of the day of the week ('d') and short name of the day of the week ('DY') because the day one of the week depends on NLS_TERRITORY.
Here is the code...
WITH
tbl AS
(
Select SYSDATE - (LEVEL - 1) "A_DATE", 101 - LEVEL "A_VALUE" From Dual CONNECT BY LEVEL <= 18
)
SELECT
A_DATE "A_DATE",
To_Char(A_DATE, 'd') "A_DAY_OF_WEEK",
To_Char(A_DATE, 'DY') "A_DAY_OF_WEEK_NAME",
A_VALUE "TBL_VALUE",
CASE WHEN To_Char(A_DATE, 'd') = '6' THEN
(Select A_VALUE From tbl Where A_DATE = t1.A_DATE - 1)
WHEN To_Char(A_DATE, 'd') = '7' THEN
(Select A_VALUE From tbl Where A_DATE = t1.A_DATE - 2)
ELSE
A_VALUE
END "VALUE_OUT"
FROM
tbl t1
ORDER BY A_DATE
... and the result
--
-- R e s u l t
--
-- A_DATE A_DAY_OF_WEEK A_DAY_OF_WEEK_NAME TBL_VALUE VALUE_OUT
-- --------- ------------- ------------------ ---------- ----------
-- 03-AUG-22 3 WED 83 83
-- 04-AUG-22 4 THU 84 84
-- 05-AUG-22 5 FRI 85 85
-- 06-AUG-22 6 SAT 86 85
-- 07-AUG-22 7 SUN 87 85
-- 08-AUG-22 1 MON 88 88
-- 09-AUG-22 2 TUE 89 89
-- 10-AUG-22 3 WED 90 90
-- 11-AUG-22 4 THU 91 91
-- 12-AUG-22 5 FRI 92 92
-- 13-AUG-22 6 SAT 93 92
-- 14-AUG-22 7 SUN 94 92
-- 15-AUG-22 1 MON 95 95
-- 16-AUG-22 2 TUE 96 96
-- 17-AUG-22 3 WED 97 97
-- 18-AUG-22 4 THU 98 98
-- 19-AUG-22 5 FRI 99 99
-- 20-AUG-22 6 SAT 100 99

How to get different distinct sales from same table

Im having trouble to get the distinct sales from my DB, I tried INNER JOIN but it doesn't work. My SQL statement is something like this:
SELECT * FROM (SELECT DISTINCT(mta.Maintenance.userId) AS a
FROM mta.Maintenance WHERE 1=1) AS t
INNER JOIN mta.Maintenance
ON t.a = mta.Maintenance.userId
WHERE 1=1
AND mta.Maintenance.paymentStatus = 'PAID'
AND mta.Maintenance.createdAt < 1648771199000
AND mta.Maintenance.createdAt > 1640995199000
AND mta.Maintenance.deletedAt IS NULL
AND mta.Maintenance.price > 50
And the table is something like this:
a
maintenanceId
adminId
storeId
vehicleId
serviceId
paymentStatus
status
createdAt
userId
65
50
\N
6
26
38
PAID
PENDING
1644237405347
65
71
70
28
3
32
32
PAID
PENDING
1644499807732
71
71
72
52
3
34
30
PAID
PENDING
1644851796531
71
78
75
52
6
36
38
PAID
PENDING
1644858138158
78
78
76
52
6
37
91
PAID
PENDING
1644863060421
78
And I want:
a
maintenanceId
adminId
storeId
vehicleId
serviceId
paymentStatus
status
createdAt
userId
65
50
\N
6
26
38
PAID
PENDING
1644237405347
65
71
70
28
3
32
32
PAID
PENDING
1644499807732
71
78
75
52
6
36
38
PAID
PENDING
1644858138158
78
Basically the distincts results with the MIN(createdAt).
Thanks!!
Try using ROW_NUMBER() to group the rows by UserId and assign a sort number based on the CreatedAt value. Then grab rows where SortNum = 1
WITH cte AS (
SELECT *, ROW_NUMBER() OVER(PARTITION BY UserId ORDER BY CreatedAt ASC) AS SortNum
FROM Maintenance
)
SELECT *
FROM cte
WHERE RowNum = 1
a
maintenanceId
adminId
storeId
vehicleId
serviceId
paymentStatus
status
createdAt
userId
RowNum
65
50
N
6
26
38
PAID
PENDING
1644237405347
65
1
71
70
28
3
32
32
PAID
PENDING
1644499807732
71
1
78
75
52
6
36
38
PAID
PENDING
1644858138158
78
1
db<>fiddle here
Try using the MySQL IN Operator of MySQL and from there select the min(createdat) column and group them by a in the main query.
SELECT * FROM maintenance a
WHERE createdat
IN (SELECT MIN(createdat) FROM maintenance b WHERE b.a=a.a)
GROUP BY a;
RESULT
a maintenanceId adminId storeId vehicleId serviceId paymentStatus STATUS createdAt userId
------ ------------- ------- ------- --------- --------- ------------- ------- ------------- --------
65 50 (NULL) 6 26 38 PAID PENDING 1644237405347 65
71 70 28 3 32 32 PAID PENDING 1644499807732 71
78 75 52 6 36 38 PAID PENDING 1644858138158 78

Calculate the number of users based on the below conditions by writing a single query SQL

There are two campaigns running campaign A and Campaign B and list of user ids participated in those two campaign is given below. Calculate the number of users based on the below conditions by writing a single query.
Participated in campaign A
Participated in campaign B
Participated in campaign A only
Participated in campaign B only
Participated in both the campaigns
Participated in either campaign A or Campaign B
Campaign A Campaign B
user_id user_id
91 62
27 11
58 16
50 92
64 17
65 71
54 12
98 37
78 93
24 58
31 54
73 94
63 85
72 30
94 32
20 1
38 48
8 99
43 45
33 46
26 39
100 29
61 49
87 73
84 81
15 88
80 70
77 33
40 55
82
42
56
95
88
I am not able to figure out how to write in single SQL query.
Assuming you have two different tables, you can use union all and aggregation:
select in_a, in_b, count(*) as num_users
from ((select user_id, 1 as in_a, 0 as in_b
from a
) union all
(select user_id, 0 as in_a, 1 as in_b
from b
)
) u
group by in_a, in_b;
This gives you all the information you need. You can use group by in_a, in_b with rollup to get all combinations.
Or, you can summarize this into one row:
select sum(in_a) as in_a, sum(in_b) as in_b,
sum(in_a * (1 - in_b)) as in_a_only,
sum(in_b * (1 - in_a)) as in_b_only,
sum(in_a * in_b) as in_ab
from ((select user_id, 1 as in_a, 0 as in_b
from a
) union all
(select user_id, 0 as in_a, 1 as in_b
from b
)
) u;
Note: These both assume that users are unique in each campaign. If not, just use select distinct or union in the subquery.

printing numbers 1 to 100 with 10 numbers per line

In a re-print of a deleted question an hour ago,
if I wanted to print out the numbers 1-100, with 10 numbers to a line
in the mysql shell, how would I go about doing that?
Community wiki answer so as not to collect points. Edit at will.
select theAnswer
from
( select #rn:=#rn+1 as rownum,
concat(1+(#rn-1)*10,' ',2+(#rn-1)*10,' ',3+(#rn-1)*10,' ',4+(#rn-1)*10,' ',5+(#rn-1)*10,' ',
6+(#rn-1)*10,' ',7+(#rn-1)*10,' ',8+(#rn-1)*10,' ',9+(#rn-1)*10,' ',10+(#rn-1)*10,' ') as theAnswer
from (select #rn:=0) params1
cross join (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 union select 10) params2
) xDerived;
+---------------------------------+
| theAnswer |
+---------------------------------+
| 1 2 3 4 5 6 7 8 9 10 |
| 11 12 13 14 15 16 17 18 19 20 |
| 21 22 23 24 25 26 27 28 29 30 |
| 31 32 33 34 35 36 37 38 39 40 |
| 41 42 43 44 45 46 47 48 49 50 |
| 51 52 53 54 55 56 57 58 59 60 |
| 61 62 63 64 65 66 67 68 69 70 |
| 71 72 73 74 75 76 77 78 79 80 |
| 81 82 83 84 85 86 87 88 89 90 |
| 91 92 93 94 95 96 97 98 99 100 |
+---------------------------------+
The stuff inside of the from ( ) is a derived table, and every derived table needs an alias, which is xDerived.
#rn is a row number variable. It gets initialized in the params1 derived table. One row.
params2 is another derived table, with rows 1 to 10 as values.
The cross join creates a cartesian product (all permutations) of a 1x10 which results in 10 rows, with #rn getting incremented with each row.
As we only want one column of output, the outer wrapper does the final select for just one column to avoid outputting the row number column.
If one wanted to use a WHILE DO loop in mysql, one could use a stored procedure.
Generally what i do is create a table (normally a temp table) and populate that with a stored procedure.
CREATE TABLE `numTable` (
`Id` int(11) NOT NULL auto_increment,
PRIMARY KEY (`Id`)
)//
CREATE PROCEDURE dowhile(IN tableLimit INT)
BEGIN
DECLARE pointer INT DEFAULT tableLimit;
WHILE pointer > 0 DO
INSERT numTable VALUES (NULL);
SET pointer = pointer - 1;
END WHILE;
END//
CALL dowhile(100)//
now you may need to use DELIMITER but for the sake of consistency i have just copied what worked in SQL Fiddle by setting the Schema Delimiter to be // (forth button bellow the Schema Window)
then from there i then do a select of this table by giving each row a group id. since you want groups of 10 i have set the group to be multiples of 10 and then group by this group id using GROUP_CONCAT to make the rows.
select myRow
from (
SELECT group_concat(id SEPARATOR ', ') as `myRow`, CEIL(id/10) as `groupId`
FROM numTable group by `groupID`) as myTable;
SQL Fiddle
since we don't want to show the group id i then make this a sub-select and only select my new rows. if you use this in something like PHP or C# to output the rows you can just do the one select since you don't have to output everything you get from a query result.
In MariaDB with the sequence plugin:
select group_concat(seq order by seq separator ' ')
from seq_1_to_100
group by (seq-1) div 10;
| group_concat(seq order by seq separator ' ') |
|----------------------------------------------|
| 1 2 3 4 5 6 7 8 9 10 |
| 11 12 13 14 15 16 17 18 19 20 |
| 21 22 23 24 25 26 27 28 29 30 |
| 31 32 33 34 35 36 37 38 39 40 |
| 41 42 43 44 45 46 47 48 49 50 |
| 51 52 53 54 55 56 57 58 59 60 |
| 61 62 63 64 65 66 67 68 69 70 |
| 71 72 73 74 75 76 77 78 79 80 |
| 81 82 83 84 85 86 87 88 89 90 |
| 91 92 93 94 95 96 97 98 99 100 |
A generic solution:
set #num_cols := 10;
set #max := 100;
select group_concat(seq order by seq separator ' ')
from seq_1_to_1000000
where seq <= #max
group by (seq-1) div #num_cols
order by min(seq);
If you want them all in one cell:
select group_concat(col separator '\n')
from (
select group_concat(seq order by seq separator '\t') as col
from seq_1_to_1000000
where seq <= #max
group by (seq-1) div #num_cols
) drv
Want to have columns?
set #num_cols := 7;
set #num_rows := 3;
set #sql := (
concat('select ', (
select group_concat('(seq-1)*', #num_cols, '+', seq, ' as c', seq)
from seq_1_to_1000000
where seq <= #num_cols
),' from seq_1_to_1000000 where seq<=', #num_rows)
);
prepare stmt from #sql;
execute stmt;
| c1 | c2 | c3 | c4 | c5 | c6 | c7 |
|----|----|----|----|----|----|----|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
If you don't have MariaDB with the sequence plugin, you can create a helper table with sequence numbers. Ask Drew how to do that :-)

how do i join two different tables in mysql

This is table1:
id name m1 m2 m3 total itemno
1 raj 10 10 10 30 1
2 ram 60 60 60 180 1
3 kumar 70 70 70 210 1
4 kanna 50 50 50 150 1
5 vivek 64 64 91 200 1
5 vivek 90 90 90 270 2
This is table2:
id name mark1 mark2 mark3 itemno
101 vivek 78 78 78 1
102 vivekkanna 89 88 78 1
103 rajagopalan 97 90 98 1
104 kumar 69 54 56 1
101 vivek 90 90 90 2
I want to join these two tables like this into a result set that looks like this:
id name m1 m2 m3 total mark1 mark2 mark3 item no
1 raj 10 10 10 30 0 0 0 1
2 ram 60 60 60 180 0 0 0 1
3 kumar 70 70 70 210 69 54 56 1
4 kanna 50 50 50 150 0 0 0 1
5 vivek 64 64 91 200 78 78 78 1
5 vivek 90 90 90 270 90 90 90 2
Seems you want a regular LEFT JOIN, returning a default value if the row in table2 does not exist;
SELECT t1.id, t1.name, t1.m1, t1.m2, t1.m3,
COALESCE(t2.mark1, 0) mark1, COALESCE(t2.mark2, 0) mark2, t1.itemno
FROM table1 t1
LEFT JOIN table2 t2 ON t1.name = t2.name AND t1.itemno = t2.itemno
ORDER BY t1.id, t1.itemno
An SQLfiddle to test with
We use a LEFT JOIN to get the default NULL value for all table2 fields that don't match with a row in table1, then COALESCE to turn them into 0 instead.