results with between and count in a select - mysql

How can I make a list where I need the orders to be between the date '2018/10/01' and '2018/10/01', but also only show the customers with more than one order?
I have these orders, but they only work for me separately.
NEW: "The big problem I have is that there are cliente that are repeated in the pedido, but one has the date within the range and the other does not, so you need to filter having a repeated cliente but with at least one pedido within the date 'fecha_ped'."
ejecution:
SELECT cliente.num_cli, nombre, apellidos, fecha_ped
FROM cliente,pedido
where pedido.cliente=cliente.num_cli
group by (pedido.num_ped)
having pedido.fecha_ped between '2018/10/01' and '2018/10/15' ;
this return:
104 Úrsula Delta Camacho 2018-10-05
102 María Sánchez Cid 2018-10-05
106 Pedro Jiménez Ruiz 2018-10-05
105 Carmen Hernández Pío 2018-10-05
107 Raúl Rodrigo Roca 2018-10-05
ejecution2:
SELECT cliente.num_cli, nombre, apellidos, fecha_ped
FROM repartocomidas_tarea5.cliente,pedido
where pedido.cliente=cliente.num_cli
group by (pedido.cliente )
having count(pedido.cliente)>=2 ;
this return:
101 Luis Ramírez Pardo 2018-09-21
102 María Sánchez Cid 2018-09-21
105 Carmen Hernández Pío 2018-09-21
104 Úrsula Delta Camacho 2018-09-22
107 Raúl Rodrigo Roca 2018-09-22
the table pedido contains these columns:
num_ped,fecha_ped, hora_servir,hora_ped,hora_entrega,cliente
the table cliente contains these columns:
num_cli,nombre,apellidos,domicilio,cod_postal,localidad,telefono,tipo_cli,bono_canjebale.
the values of pedido:
100101 2018-09-21 10:00:00 14:30:00 14:35:00 101
100107 2018-09-22 10:55:00 14:30:00 null 101
100102 2018-09-21 10:15:00 14:00:00 13:58:00 102
100110 2018-10-05 10:05:00 14:00:00 14:05:00 102
100103 2018-09-21 10:30:00 15:00:00 null 103
100106 2018-09-22 11:08:00 14:15:00 14:20:00 104
100109 2018-10-05 11:56:00 14:45:00 14:48:00 104
100104 2018-09-21 10:44:00 14:30:00 14:40:00 105
100112 2018-10-05 12:25:00 14:15:00 14:20:00 105
100111 2018-10-05 11:34:00 14:30:00 14:38:00 106
100108 2018-09-22 11:56:00 13:45:00 14:01:00 107
100113 2018-10-05 09:45:00 13:45:00 13:56:00 107
100105 2018-09-21 10:56:00 14:00:00 14:08:00 108
values of cliente:
101 Luis Ramírez Pardo
102 María Sánchez Cid
103 Martín Guerrero López
104 Úrsula Delta Camacho
105 Carmen Hernández Pío
106 Pedro Jiménez Ruiz
107 Raúl Rodrigo Roca
108 Soledad Campillo Molina
109 Lucía Gómez Prados

To combine results use UNION ALL. But make sure they have the same column to select
SELECT cliente.num_cli, nombre, apellidos, fecha_ped
FROM cliente,pedido
where pedido.cliente=cliente.num_cli
group by (pedido.num_ped)
having pedido.fecha_ped between '2018/10/01' and '2018/10/15'
UNION ALL
SELECT cliente.num_cli, nombre, apellidos, fecha_ped
FROM repartocomidas_tarea5.cliente,pedido
where pedido.cliente=cliente.num_cli
group by (pedido.cliente )
having count(pedido.cliente)>=2 ;
But if you want for the result to meet both condition try this.
SELECT cliente.num_cli, nombre, apellidos, fecha_ped
FROM repartocomidas_tarea5.cliente,pedido
where pedido.cliente=cliente.num_cli
group by (pedido.cliente,pedido.num_ped )
having count(pedido.cliente)>=2 AND (pedido.fecha_ped between '2018/10/01' and '2018/10/15');
but if you want just either of the condition change your having to OR like this
having count(pedido.cliente)>=2 OR (pedido.fecha_ped between '2018/10/01' and '2018/10/15');

May I add another suggestion.
SELECT cliente.num_cli, nombre, apellidos, min(fecha_ped),max(fecha_ped),count(*)
FROM cliente JOIN pedido
ON cliente.num_cli=pedido.cliente
WHERE pedido.fecha_ped between '2018-10-01' and '2018-10-15'
GROUP BY pedido.cliente
having COUNT(*) >=2 ;
Edit:
After looking at your data (and creating a fake test data on my side), I've come up with this query below:
SELECT *,COUNT(*) AS "Total Orders"
FROM cliente a LEFT JOIN pedido b ON a.num_cli=b.cliente
WHERE b.fecha_ped BETWEEN '2018-10-01' AND '2018-10-15' GROUP BY num_cli;
The COUNT(*) AS "Total Orders" will show how many orders GROUP BY num_cli between the date you requested. This will show all results.
By adding HAVING COUNT(*) >=2; like query below, will only show cliente that have ordered more than once:
SELECT *,COUNT(*) AS "Total Orders"
FROM cliente a LEFT JOIN pedido b ON a.num_cli=b.cliente
WHERE b.fecha_ped BETWEEN '2018-10-01' AND '2018-10-15' GROUP BY num_cli
HAVING COUNT(*) >=2;
*I edited the b.hora_servir to b.fecha_ped
Edit 2:
Ok, I'm just trying something here. Tell me if this is at least close to what you try to achieve.
SELECT * FROM
(SELECT num_cli,nombre,apellidos,TotalOrders,IF(mdate BETWEEN '2018-10-01' AND '2018-10-15',CONCAT("Last Purchase date on ",mdate),"None") AS "Checking" FROM
(SELECT num_cli,nombre,apellidos,MAX(fecha_ped) mDate,COUNT(*) AS "TotalOrders"
FROM cliente a LEFT JOIN pedido b ON a.num_cli=b.cliente
WHERE b.fecha_ped BETWEEN '2018-10-01' AND '2018-10-15' GROUP BY num_cli
UNION
SELECT num_cli,nombre,apellidos,MAX(fecha_ped) mDate,COUNT(*) AS "TotalOrders"
FROM cliente a LEFT JOIN pedido b ON a.num_cli=b.cliente
WHERE b.fecha_ped NOT BETWEEN '2018-10-01' AND '2018-10-15' GROUP BY num_cli
ORDER BY num_cli) a) b WHERE (TotalOrders=2 OR checking <> "None");

You can do like this :
SELECT DISTINCT(p.cliente),c.num_cli, nombre, apellidos, fecha_ped
FROM pedido AS p
LEFT JOIN cliente AS c ON p.cliente=c.num_cli
WHERE p.fecha_ped >= DATE_FORMAT('YYYY/MM/DD','2018/10/01') AND p.fecha_ped <= DATE_FORMAT('YYYY/MM/DD','2018/10/15') HAVING COUNT(p.cliente)>=2;

In the end I found the solution using a condition to the result of the union of the tables.
SELECT NUMERO , nombre, apellidos FROM
(
(SELECT cliente.num_cli AS NUMERO, CLIENTE.num_cli AS NC, nombre, apellidos, fecha_ped AS FECHA, num_ped, total_pedido as TOTAL
FROM cliente,pedido
where pedido.cliente=cliente.num_cli
group by (pedido.num_ped)
having pedido.fecha_ped between '2018/10/01' and '2018/10/15')
UNION
(SELECT cliente.num_cli AS NUMERO,CLIENTE.num_cli AS NC, nombre, apellidos, fecha_ped AS FECHA, num_ped, COUNT(pedido.cliente) AS TOTAL
FROM repartocomidas_tarea5.cliente,pedido
where pedido.cliente=cliente.num_cli
group by (pedido.cliente )
having (count(pedido.cliente)>=2) )
)
AS RESULTADO
WHERE NUMERO=NC
GROUP BY numero
having (count(nombre)>=2) order by NUMERO ;
;
RESULT:
NUMERO nombre apellidos
102 María Sánchez Cid
104 Úrsula Delta Camacho
105 Carmen Hernández Pío
107 Raúl Rodrigo Roca

Your problem is that you are creating a new column with the numbers of pedidos of each client, so you can avoid this column to fix your problem.
Think that you are trying to insert the query values into a table that dont have the same numbers of columns.
Here you code fixed.
insert into cliente_vip (num_cli, nombre, apellidos)
select p.cliente, c.nombre, c.apellidos
from pedido p
inner join cliente c
on c.num_cli = p.cliente
where p.fecha_ped between '2018-10-01' and '2018-10-15'
group by p.cliente having count(p.cliente) >= 2;

Related

rank on mysql with join

i need to display rank with my sql on 2 joined table, there's my mysql query to display
SELECT a.UserID, b.Nama,a.Matematika,a.IPA,a.IPS,a.BIND,a.BING,a.Rata,
FIND_IN_SET( a.Rata, (SELECT GROUP_CONCAT( a.Rata ORDER BY a.Rata DESC ) FROM datanilaiujian )) AS rank
from datanilaiujian as a JOIN
datauser as b
ON a.UserID=b.UserID
ORDER BY a.Rata DESC
but when i execute this command, mysql return Error Code: 1242. Subquery returns more than 1 row
list field on table datanilaiujian
UserID Matematika IPA IPS BIND BING Rata
1000 90 76 78.9 78 65 77.58
1001 78.9 87 67 56 78 73.38
1002 80 78.9 67 55 65.9 69.36
1003 78.9 56 77 88 90 77.97999999999999
list field on table datauser
UserID Pass Nama Alamat NoTelepon AsalSekolah Tanggal Masuk NilaiUN
1000 1000 Habib Jl.sesama 232323232323 23dsdsdsfsdfsdfsdfsdff 2017-01-13 19:35:22 Sudah
1001 1001 wisnu jl sesama 085600336706 SMA 2 Purwokerto 2017-01-28 17:35:32 Sudah
1002 1002 Arif Jl Sungkio 085600336706 SMA BINTEK 2017-01-28 19:30:56 Sudah
1003 1003 Akbar Jl sesama 085600133558 SMPN 1 Purwokerto 2017-02-02 18:59:47 Sudah
my expected result :
Nama Matematika IPA IPS BIND BING Rata Rank
I see the problem. Your subquery is saying a.Rata. This refers to the outer table. I suspect that the GROUP_CONCAT() is then confusing MySQL, so the subquery is not interpreted as an aggregation query.
However, you should move the subquery to the FROM clause:
SELECT a.*,
FIND_IN_SET( a.Rata, l.list) AS rank
from datanilaiujian a JOIN
datauser b
ON a.UserID = b.UserID CROSS JOIN
(SELECT GROUP_CONCAT( a2.Rata ORDER BY a2.Rata DESC ) as list
FROM datanilaiujian a2
) l
ORDER BY a.Rata DESC;
This generally helps the optimizer choose the best execution plan.

MySql Insert Into Select Sum

TABLE ONE DATA - po_header
PO_ID PROJ_ID SUP_ID TOT_SUM SUBM_DATE
32 5555 AccAYOU 99.00 2016-11-29
33 5555 AccAYOU 990.00 2016-11-29
34 25412 AccAYOU 248778595.08 2016-11-30
TABLE TWO DATA - po_details
PO_ID amount
32 110.00
33 1500000.00
34 565079266.00
34 1.00
How can I Run the following SQL ?
INSERT INTO po_header (TOT_SUM) VALUES (SELECT SUM(amount)
FROM po_details WHERE PO_ID = '34') WHERE PO_ID ='34';
Even it's un correct syntax but this is what you want:
UPDATE po_header h
SET TOT_SUM = (Select sum(amount) From po_details d Where d.po_id = h.po_id)
UPDATE po_header SET TOT_SUM = (SELECT SUM(amount) FROM po_details WHERE PO_ID='34') WHERE PO_ID='34';

join 2 mysql select based on text field

I have the 2 following select in Mysql:
1st select:
(SELECT DISTINCT `Online_playerdatabase_v2`.`Player`,
Online_playerdatabase_v2.First_Deposit_Date As FirstDep,
TRUNCATE(Online_playerdatabase_v2.Balance,2) as Balance
FROM Online_playerdatabase_v2
WHERE `Online_playerdatabase_v2`.`Player`<>'Player'
ORDER BY `Online_playerdatabase_v2`.`Balance` DESC;
2d select:
SELECT DISTINCT(Online_customer_activity_v2.Customers) as Player,
max(Online_customer_activity_v2.Date) as LastAction
FROM Online_customer_activity_v2
WHERE `Online_customer_activity_v2`.`Total_Bets`>0
Group by Online_customer_activity_v2.Customers
Output Select 1
Player FirstDep Balance
Ray 2014-10-19 9100.00
Ramzi 2014-11-02 9.61
tareq 2014-11-06 805.00
STAN 2014-10-17 7.50
Bill 2014-03-25 68.40
karam 2014-11-16 676.50
Abdul 2014-11-13 650.00
Renaud 2014-03-12 507.00
John 2014-11-22 500.00
Output select 2
Player LastAction
John 2015-11-13
Bill 2014-12-14
Renaud 2015-03-14
Abdul 2015-11-16
Ray 2015-11-22
STAN 2015-10-29
Ramzi 2015-11-10
Tarek 2015-05-10
karam 2014-12-10
Abdul 2015-02-10
Desired Output, a join on both Select that adds following calculations:
active days (FirstDep-LastAction) and Days_last_Visit (CurrentDate - Last Action)
Summarized in following table:
Player FirstDep Balance LastAction Active_days Days_last_Visit
Ray 2014-10-19 9100.00 2015-11-22 399 1
Ramzi 2014-11-02 9.61 2015-11-10 373 13
tareq 2014-11-06 805.00 2015-05-10 185 197
STAN 2014-10-17 7.50 2015-10-29 377 25
Bill 2014-03-25 68.40 2014-12-14 264 344
karam 2014-11-16 676.50 2014-12-10 24 348
Abdul 2014-11-13 650.00 2015-02-10 89 286
Renaud 2014-03-12 507.00 2015-03-14 367 254
John 2014-11-22 500.00 2015-11-13 356 10
Your help is greatly appreciated!
Thanks
The following query should give the result you want. I will add that I joined the two tables from your intermediate queries above using the Player field. This is not a very robust way to join, because the name may not be unique among all players in the table. A better way to join would be to use a unique identifier of some sort.
SELECT t1.Player, t1.FirstDep, t1.Balance, t2.LastAction,
DATEDIFF(t2.LastAction, t1.FirstDep) AS Active_days,
DATEDIFF(NOW(), t2.LastAction) AS Days_last_Visit
FROM
(
SELECT DISTINCT `Online_playerdatabase_v2`.`Player`,
Online_playerdatabase_v2.First_Deposit_Date AS FirstDep,
TRUNCATE(Online_playerdatabase_v2.Balance,2) AS Balance
FROM Online_playerdatabase_v2
WHERE `Online_playerdatabase_v2`.`Player` <> 'Player'
) t1
INNER JOIN
(
SELECT DISTINCT(Online_customer_activity_v2.Customers) AS Player,
MAX(Online_customer_activity_v2.Date) AS LastAction
FROM Online_customer_activity_v2
WHERE `Online_customer_activity_v2`.`Total_Bets` > 0
GROUP BY Online_customer_activity_v2.Customers
) t2
ON t1.`Player` = t2.`Player`
You need to join the 2 selects as subqueries in a 3rd select using the player field. The Active_days and Days_last_Visit fields can be calculated using the DateDiff() function.
SELECT *
,DateDiff(t2.LastAction,t1.FirstDep) AS Active_days
,DateDiff(CURDATE(), t2.LastAction) AS Days_last_Visit
FROM
(SELECT DISTINCT `Online_playerdatabase_v2`.`Player`,
Online_playerdatabase_v2.First_Deposit_Date As FirstDep,
TRUNCATE(Online_playerdatabase_v2.Balance,2) as Balance
FROM Online_playerdatabase_v2
WHERE `Online_playerdatabase_v2`.`Player`<>'Player'
ORDER BY `Online_playerdatabase_v2`.`Balance` DESC) t1
LEFT JOIN
(SELECT DISTINCT(Online_customer_activity_v2.Customers) as Player,
max(Online_customer_activity_v2.Date) as LastAction
FROM Online_customer_activity_v2
WHERE `Online_customer_activity_v2`.`Total_Bets`>0
Group by Online_customer_activity_v2.Customers) t2
ON t1.Player=t2.Player
You have to consider, however, how you join the 2 datasets. I used left join, since the players table will probably hold all players, but you may want to go for inner join or simulate a full outer join depending your requirements and your data.

Group similar items

Here is my table structure with data
id actor_id created_at updated_at
729 80 2012-09-10 17:05:59 2012-09-10 17:05:59
731 80 2012-09-10 17:04:02 2012-09-10 17:04:02
725 139 2012-09-06 13:59:08 2012-09-06 13:59:08
724 76 2012-09-06 11:31:30 2012-09-06 11:31:30
723 29 2012-09-06 09:40:22 2012-09-06 09:40:22
719 29 2012-09-06 09:24:02 2012-09-06 09:24:02
811 80 2012-09-02 17:05:59 2012-09-10 17:05:59
812 80 2012-09-01 17:04:02 2012-09-10 17:04:02
This is the result of
SELECT `te`.`id`, te.actor_id, te.created_at, te.created_at
FROM `timeline_events` AS te
ORDER BY
te.created_at DESC
LIMIT 10
I need group it by actor_id and created_at
Here is what i need in the end
id actor_id created_at updated_at count
729 80 2012-09-10 17:05:59 2012-09-10 17:05:59 2
725 139 2012-09-06 13:59:08 2012-09-06 13:59:08 1
724 76 2012-09-06 11:31:30 2012-09-06 11:31:30 1
723 29 2012-09-06 09:40:22 2012-09-06 09:40:22 2
812 80 2012-09-10 17:04:02 2012-09-10 17:04:02 2
Can someone guide me how to do this?
Many thanks in advance
UPD To simplify i will put another example
So say i have next rows
1 1 (count: 2)
1
3 3 (count: 1)
4
4 => after magic function it should be 4 (count: 2)
1
1 1 (count: 3)
1
6 6 (count: 2)
6
4 4 (count 3)
4
4
So it should split by groups.
UPD 2
I need this query for rendering timeline. Right now it show all info what user did, but i need group it.
Before
user1 upload photo
user1 changed information
user2 updated bio
user3 uploaded photo
user3 updated bio
user1 update bio
After
user1 uploadd photo and changed infomarion
user2 updated bio
user3 uploaded photo and updated bio
user1 updated bio
I think this might be what you are trying to do:
select t1.id,
t1.actor_id,
max(created_at) created_at,
updated_at,
t2.total
from yourtable t1
left join
(
select count(*) total, date(created_at) dt, actor_id
from yourtable
group by actor_id, date(created_at)
) t2
on t1.actor_id = t2.actor_id
and date(t1.created_at) = t2.dt
group by t1.actor_id, date(t1.created_at)
order by t1.created_at desc
see SQL Fiddle with demo
I am grouping by actor_id and the date using the DATE() function
I find solution by myself
Here is the query
SET #i = 0;
SELECT
COUNT(`wrapper`.`id`) AS 'count',
GROUP_CONCAT(`wrapper`.`type` SEPARATOR ',') as 'types'
FROM (
SELECT
#prev := (
SELECT prev_te.actor_id
FROM `timeline_events` AS prev_te
WHERE prev_te.created_at > te.created_at
ORDER BY prev_te.created_at ASC
LIMIT 1
) AS 'prev_actor_id',
IF(
#prev = te.`actor_id` OR #prev IS NULL,
#i,
#i := #i + 1
) AS 'actor_id_group',
`te`.*
FROM `timeline_events` AS te
ORDER BY
te.created_at DESC,
te.id DESC
) AS `wrapper`
GROUP BY `wrapper`.`actor_id_group`
LIMIT 10
And here is the proof link ;-)
This website really helped me
I am using wrapper for grouping purpose, because mysql didn't group by variables, if someone know better solution, please let me know
SELECT te.id, te.actor_id, te.created_at, te.updated_at ,
COUNT(*) FROM timeline_events AS te GROUP BY te.actor_id,
te.created_at ORDER BY
te.created_at DESC
LIMIT 10
Add GROUP BY actor_id before order by clause.
Latest edit:
select distinct actor_id, count(actor_id), created_at from actors group by actor_id
order by created_at desc;

Join condition retrieving undesired answer

I have 2 tables and is as follows
select Event_ID,[Gross Salary] from tblEar where Event_ID=14
Result:
Event_ID Gross Salary
14 56128
14 51984
14 42028
And:
select EventId, [Order Date],Amount from tblBudget where EventId=14
Result:
EventId Order Date Amount
14 10/10/2011 20000
14 10/10/2011 20000
14 20/03/2012 2500
14 02/04/2012 -50000
if i write a join statment on these 2 tables to get it is retrieving duplicate records.I used Distinct But no Positive Result.
select DISTINCT tba.[Order Date],ISNULL(tba.Amount,0),ISNULL(te.[Gross Salary],0) from tblBudget tba
join
tblEar te on tba.EventId=te.Event_ID where tba.EventId=14
I got the following ans:
Order Date (No column name) (No column name)
2011-10-10 20000.00 42028.00
2011-10-10 20000.00 51984.00
2011-10-10 20000.00 56128.00
2012-03-20 2500.00 42028.00
2012-03-20 2500.00 51984.00
2012-03-20 2500.00 56128.00
2012-04-02 -50000.00 42028.00
2012-04-02 -50000.00 51984.00
2012-04-02 -50000.00 56128.00
Can any one show the Way to get Accuarate data
I guess you want to group the data and aggregate the amounts:
SELECT tba.[Order Date], SUM(tba.Amount), SUM(te.[Gross Salary])
FROM tblBudget tba
JOIN tblEar te on tba.EventId = te.Event_ID
WHERE tba.EventId = 14
GROUP BY tba.[Order Date]