sql statement mysql notcorrect - mysql

SELECT SUBSTRING(m.own,3,4) as c , (select amphur.AMPHUR_NAME where c = SUBSTRING(m.own,3,4) ),
COUNT(* ) AS cnt
FROM MEMBER AS m
GROUP BY SUBSTRING(m.own,3,4)
order by cnt desc
sql statement mysql
what wrong with code below when i fill
(select amphur.AMPHUR_NAME where c = SUBSTRING(m.own,3,4) )
it error
CREATE TABLE IF NOT EXISTS `member` (
`idmember` int(11) NOT NULL AUTO_INCREMENT,
`own` varchar(255) DEFAULT NULL,
`Sname` varchar(255) DEFAULT NULL,
`Ssurname` varchar(255) DEFAULT NULL,
`Sex` enum('¿','¿') NOT NULL,
`Hno` varchar(255) DEFAULT NULL,
`Moo` varchar(255) DEFAULT NULL,
`tambol` varchar(200) NOT NULL,
`dateofbirth` date DEFAULT NULL,
`migratedate` date DEFAULT NULL,
`status` enum('5','4','3','2','1') DEFAULT '5',
`Unit` int(4) DEFAULT NULL,
`staff1` int(11) DEFAULT NULL,
`staff2` int(11) DEFAULT NULL,
`fathercode` varchar(30) NOT NULL,
`mathercode` varchar(30) NOT NULL,
PRIMARY KEY (`idmember`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=8994 ;
CREATE TABLE IF NOT EXISTS `amphur` (
`AMPHUR_ID` int(5) NOT NULL AUTO_INCREMENT,
`AMPHUR_CODE` varchar(4) COLLATE utf8_unicode_ci NOT NULL,
`AMPHUR_NAME` varchar(150) COLLATE utf8_unicode_ci NOT NULL,
`GEO_ID` int(5) NOT NULL DEFAULT '0',
`PROVINCE_ID` int(5) NOT NULL DEFAULT '0',
`province_name` varchar(80) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`AMPHUR_ID`),
KEY `province_name` (`province_name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=999 ;

Your subquery is missing a From clause:
SELECT SUBSTRING(m.own,3,4) as c
, (select amphur.AMPHUR_NAME
From amphur
Where ??? = SUBSTRING(m.own,3,4) )
, COUNT(* ) AS cnt
FROM MEMBER AS m
However, how does the amphur table relate to the member table?

You cannot use aliases in the same level.
Even if you could, you are filtering on non-correlated columns in your subquery: the subquery would just return the record from amphur if there is one record, or an error if there are more.
Could you please provide some sample data and the desired recordset?

there is no "FROM" clause in your select Amphur.amphur_name

Related

How to optimize MySQL query with multiple identical subqueries and multiple grouping

Problem statement
The two identical sub-queries (i.e., "a" and "b") are used to derive sub-query "n" which I further aggregate to get the final result. The response time of the query is not optimal, can anyone share some ideas to help optimize? I tried to comebine "a" and "b" as well as "a" and "n" but neither turns out to be dead ends per my knowledge...
select n.businessLiaision,
n.channel,
n.name,
n.dt,
n.ifNew,
count(n.productRowId),
sum(n.totalQty),
sum(n.totalAmount)
from ( select a.productRowId,
a.name,
a.rowId,
a.dt,
a.businessLiaision,
a.channel,
a.ct,
a.totalQty,
a.totalAmount,
case when a.ct = sum(b.ct) then 'true' else 'false' end as 'ifNew'
from ( select d.productRowId,
p.name,
DATE_FORMAT(o.effectiveTime, '%m/%Y') as 'dt',
p.rowId,
p.businessLiaision,
p.channel,
count(*) as 'ct',
sum(d.qty) as 'totalQty',
sum(d.amountPostDiscount) as 'totalAmount'
from transactionParty as p
join transactionOrderHist as o on p.rowId = o.transactionPartyRowId
join transactionOrderDetailHist as d on o.rowId = d.orderRowId
where o.businessType = 'sales'
group by d.productRowId, p.name, DATE_FORMAT(o.effectiveTime, '%m/%Y'), p.rowId, p.businessLiaision, p.channel
) as a
left join ( select d.productRowId,
p.name,
DATE_FORMAT(o.effectiveTime, '%m/%Y') as 'dt',
count(*) as 'ct'
from transactionParty as p
join transactionOrderHist as o on p.rowId = o.transactionPartyRowId
join transactionOrderDetailHist as d on o.rowId = d.orderRowId
where o.businessType = 'sales'
group by d.productRowId, p.name, DATE_FORMAT(o.effectiveTime, '%m/%Y')
) as b on b.productRowId = a.productRowId and b.name = a.name and b.dt <= a.dt
group by a.productRowId, a.name, a.rowId, a.dt, a.ct, a.businessLiaision, a.channel, a.ct, a.totalQty, a.totalAmount
) as n
group by n.businessLiaision, n.channel, n.name, n.dt, n.ifNew
Explain plan result
enter image description here
Table descriptions
transactionParty
CREATE TABLE `transactionParty` (
`rowId` varchar(50) NOT NULL,
`name` varchar(100) DEFAULT NULL,
`code` varchar(20) DEFAULT NULL,
`businessLiaision` varchar(20) DEFAULT NULL,
`type` varchar(20) DEFAULT NULL,
`contractualType` varchar(20) DEFAULT NULL,
`paymentMethod` varchar(20) DEFAULT NULL,
`partyGroup` varchar(20) DEFAULT NULL,
`channel` varchar(20) DEFAULT NULL,
`costCenter` varchar(20) DEFAULT NULL,
`warehouseRowId` varchar(100) DEFAULT NULL,
`taxOption` varchar(20) DEFAULT NULL,
PRIMARY KEY (`rowId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
transactionOrderHist
CREATE TABLE `transactionOrderHist` (
`rowId` varchar(50) NOT NULL COMMENT '明道记录ID',
`orderId` varchar(50) DEFAULT NULL COMMENT '单据ID',
`orderCreationTime` datetime DEFAULT NULL COMMENT '单据创建时间',
`orderCreator` varchar(20) DEFAULT NULL COMMENT '单据创建人',
`businessType` varchar(20) DEFAULT NULL COMMENT '业务类型',
`businessLiaision` varchar(20) DEFAULT NULL COMMENT '内部业务负责人,如业务员/采购/文员',
`transactionPartyRowId` varchar(50) DEFAULT NULL COMMENT '往来单位',
`outboundWarehouse` varchar(50) DEFAULT NULL COMMENT '发货仓',
`inboundWarehouse` varchar(50) DEFAULT NULL COMMENT '收货仓',
`outboundWarehouseType` varchar(50) DEFAULT NULL,
`inboundWarehouseType` varchar(50) DEFAULT NULL,
`effectiveTime` datetime DEFAULT '0000-00-00 00:00:00' COMMENT '单据过账时间',
`orderEffectuater` varchar(20) DEFAULT NULL COMMENT '单据过账人',
`remark` varchar(200) DEFAULT NULL,
`productCount` int(10) DEFAULT NULL,
`totalUnitCount` int(10) DEFAULT NULL,
`totalCostAmount` decimal(10,0) DEFAULT NULL,
`totalPostDiscountAmount` decimal(10,0) DEFAULT NULL,
`paymentStatus` varchar(50) DEFAULT NULL,
`paymentDate` datetime DEFAULT NULL,
`outboundWarehouseRowId` varchar(50) DEFAULT NULL,
`inboundWarehouseRowId` varchar(50) DEFAULT NULL,
PRIMARY KEY (`rowId`) USING BTREE,
KEY `orderEffectiveDate` (`effectiveTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
transactionOrderDetailHist
CREATE TABLE `transactionOrderDetailHist` (
`rowId` varchar(50) NOT NULL,
`orderRowId` varchar(50) DEFAULT NULL,
`productRowId` varchar(50) DEFAULT NULL,
`qty` int(20) DEFAULT NULL,
`price` decimal(20,2) DEFAULT NULL,
`cost` decimal(20,2) DEFAULT NULL,
`amount` decimal(20,2) DEFAULT NULL,
`amountPostDiscount` decimal(20,2) DEFAULT NULL,
`type` varchar(50) DEFAULT NULL,
`effectiveTime` datetime DEFAULT NULL,
`costAmount` decimal(20,2) DEFAULT NULL,
PRIMARY KEY (`rowId`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8
FROM ( SELECT ... )
[LEFT] JOIN ( SELECT ... ) ON ...
is notoriously inefficient. Try to rewrite the query to avoid such.
Please provide EXPLAIN SELECT ...; meanwhile, I will do some guessing.
These indexes may help:
d: INDEX(orderRowId, productRowId, qty, amountPostDiscount)
o: INDEX(businessType, transactionPartyRowId, effectiveTime, rowId)
Looking at the final GROUP BY. It does not necessarily order the rows. If you want a particular order, add an ORDER BY. Be aware that the dt part is not quite in chronological order since it has month before year. The other group-bys are in derived tables, so an ORDER BY would be ignored.
If and b.name = a.name and b.dt <= a.dt is for doing "groupwise-max", that is the performance bottleneck. There are much better ways to do it. See Groupwise-Max .
If the text is in Chinese, you should consider converting to utf8mb4 -- utf8 is missing the 4-byte UTF-8 Chinese characters.
It is OK to have the PRIMARY KEY as VARCHAR(50), but it could be better to use INT. Is some outside process providing the rowId?

error in my mysql query with a limit condition

i have 3 tables
customers, times and sales
i want to find out all the customers income yearly condition is that customers with no children and income must be greater than a limit we are set
my table structure
customers
CREATE TABLE `customers` (
`customer_id` int(11) DEFAULT NULL,
`account_num` double DEFAULT NULL,
`lname` varchar(50) DEFAULT NULL,
`fname` varchar(50) DEFAULT NULL,
`mi` varchar(50) DEFAULT NULL,
`address1` varchar(50) DEFAULT NULL,
`address2` varchar(50) DEFAULT NULL,
`address3` varchar(50) DEFAULT NULL,
`address4` varchar(50) DEFAULT NULL,
`postal_code` varchar(50) DEFAULT NULL,
`region_id` int(11) DEFAULT NULL,
`phone1` varchar(50) DEFAULT NULL,
`phone2` varchar(50) DEFAULT NULL,
`birthdate` datetime DEFAULT NULL,
`marital_status` varchar(50) DEFAULT NULL,
`yearly_income` varchar(50) DEFAULT NULL,
`gender` varchar(50) DEFAULT NULL,
`total_children` smallint(6) DEFAULT NULL,
`num_children_at_home` smallint(6) DEFAULT NULL,
`education` varchar(50) DEFAULT NULL,
`member_card` varchar(50) DEFAULT NULL,
`occupation` varchar(50) DEFAULT NULL,
`houseowner` varchar(50) DEFAULT NULL,
`num_cars_owned` smallint(6) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
sales
CREATE TABLE `sales` (
`product_id` int(11) DEFAULT NULL,
`time_id` int(11) DEFAULT NULL,
`customer_id` int(11) DEFAULT NULL,
`store_id` int(11) DEFAULT NULL,
`store_sales` float DEFAULT NULL,
`store_cost` float DEFAULT NULL,
`unit_sales` double DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
times
CREATE TABLE `times` (
`time_id` int(11) DEFAULT NULL,
`the_date` datetime DEFAULT NULL,
`the_day` varchar(50) DEFAULT NULL,
`the_month` varchar(50) DEFAULT NULL,
`the_year` smallint(6) DEFAULT NULL,
`day_of_month` smallint(6) DEFAULT NULL,
`month_of_year` smallint(6) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
MY question is :-Find the list of the customers with no child and an yearly_income greater that a limit given by the user when running the query.
MY query is
SET #limit=50;
SELECT customers.`fname`, customers.`lname` ,ROUND(SUM(sales.store_sales)) as income,times.the_year
FROM `sales`
LEFT JOIN times
ON sales.time_id=times.time_id
LEFT JOIN customers
ON customers.customer_id=sales.customer_id
WHERE income>#limit AND `total_children`=0
GROUP BY sales.customer_id,times.the_year
am getting this error:#1054 - Unknown column 'income' in 'where clause'
The quantity you aliased as income is an aggregate, and therefore it does not make sense to refer to it in the WHERE clause. Move this WHERE logic to a HAVING clause:
SET #limit=50;
SELECT
c.fname,
c.lname,
ROUND(SUM(s.store_sales)) AS income,
t.the_year
FROM sales s
LEFT JOIN times t
ON s.time_id = t.time_id
LEFT JOIN customers c
ON c.customer_id = s.customer_id
WHERE
total_children = 0
GROUP BY
c.customer_id,
t.the_year
HAVING
ROUND(SUM(s.store_sales)) > #limit;
Note that technically we could have used the alias in the HAVING clause:
HAVING income > #limit;
But this would not be portable to most other databases. Also, I introduced aliases into the query, which make it easier to read.
For aggreagte columns not present in the original table you should use having clause instead of where
SET #limit=50;
SELECT customers.`fname`, customers.`lname` ,ROUND(SUM(sales.store_sales)) as income,times.the_year
FROM `sales`
LEFT JOIN times
ON sales.time_id=times.time_id
LEFT JOIN customers
ON customers.customer_id=sales.customer_id
WHERE `total_children`=0
GROUP BY customers.customer_id,times.the_year
having income>#limit
income is alias name,so can't use that in where condition.
SET #limit=50;
SELECT * FROM
(
SELECT customers.`fname`, customers.`lname` ,ROUND(SUM(sales.store_sales))
as income,times.the_year
FROM `sales` LEFT JOIN times ON sales.time_id=times.time_id
LEFT JOIN customers ON customers.customer_id=sales.customer_id
WHERE `total_children`=0
GROUP BY sales.customer_id,times.the_year
)t WHERE income>#limit
Find the list of the customers with no child and an yearly_income
greater that a limit given by the user when running the query.
Are you sure you don't want a simple query like this?
SELECT *
FROM customers AS c
WHERE yearly_income > #limit -- but why is yearly_income a VarChar(50)?
AND total_children=0

sql can't figure out the query

I have three tables:
CREATE TABLE IF NOT EXISTS `contacts` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`providerId` int(10) unsigned NOT NULL DEFAULT '0',
`requestId` int(10) unsigned NOT NULL DEFAULT '0',
`status` binary(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
)
CREATE TABLE IF NOT EXISTS `messages` (
`id` int(255) NOT NULL AUTO_INCREMENT,
`fromuid` int(255) NOT NULL,
`touid` int(255) NOT NULL,
`sentdt` datetime NOT NULL,
`read` tinyint(1) NOT NULL DEFAULT '0',
`readdt` datetime DEFAULT NULL,
`messagetext` longtext CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`id`),
KEY `id` (`id`)
)
CREATE TABLE IF NOT EXISTS `users` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`email` varchar(255) DEFAULT NULL,
`mobile` varchar(15) NOT NULL,
`password` varchar(255) NOT NULL,
`city` varchar(255) NOT NULL,
`zip` varchar(15) DEFAULT NULL,
`device` varchar(50) DEFAULT NULL,
`version` varchar(10) DEFAULT NULL,
`photo` varchar(255) DEFAULT NULL,
`created` datetime NOT NULL,
`live` enum('0','1') NOT NULL DEFAULT '1',
`authenticationTime` datetime NOT NULL,
`userKey` varchar(255) DEFAULT NULL,
`IP` varchar(50) DEFAULT NULL,
`port` int(10) DEFAULT '0',
PRIMARY KEY (`id`),
KEY `firstname` (`mobile`,`city`,`zip`)
)
And this SQL query that finds out friends/contacts for specified user (user id 1 in this case):
SELECT u.id
,u.mobile
,u.name
,(NOW() - u.authenticationTime) AS authenticateTimeDifference
,u.IP
,f.providerid
,f.requestid
,f.status
,u.port
FROM contacts f
LEFT JOIN users u ON u.id =
IF (
f.providerid = 1
,f.requestid
,f.providerid
) WHERE (
f.providerid = 1
AND f.status = 1
)
OR f.requestid = 1
That works fine but I want to be able to also join messages table and show user's friends/contacts who have talked latest (meaning latest conversations first) with order by messages.sentdt desc option but I am unable to figure out how to do that, I tried all joins but none worked :(
Your help will be greatly appreciated. Thanks
Update
Here is sample data above query returns:
In that same resultset, I want to be able to sort based on order by messages.sentdt desc but I am not sure how to pull that in and sort resultset by latest message first
Try this:
select u.id
, u.mobile
, u.name
, (NOW() - u.authenticationTime) as authenticateTimeDifference
, u.IP
, f.providerid
, f.requestid
, f.status
, u.port
from contacts f
left join users u
on u.id = if (f.providerid = 1, f.requestid, f.providerid)
left join (select fromuid, max(sentdt) as sentdt from messages group by fromuid) m
on m.fromuid = if (f.providerid = 1, f.providerid, f.requestid)
where (f.providerid = 1 and f.status = 1)
or f.requestid = 1
order by m.sentdt

Updating table A.type = B.type WHERE A.id = B.id

I have two tables in different databases:
In the database named CRMALPHA:
CREATE TABLE IF NOT EXISTS `contacts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`accountId` int(11) NOT NULL,
`Type` int(11) NOT NULL,
`fName` varchar(255) NOT NULL,
`lName` varchar(255) NOT NULL,
`title` varchar(255) NOT NULL,
`email` varchar(255) NOT NULL,
`workPhone` int(11) NOT NULL,
`workPhoneExt` int(11) NOT NULL,
`cellPhone` int(11) NOT NULL,
`altPhone` int(11) NOT NULL,
`altPhoneDescription` varchar(255) NOT NULL,
`dob` date NOT NULL,
`createdDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`createdById` int(11) NOT NULL,
`notes` varchar(255) NOT NULL,
`isDeleted` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `accountId` (`accountId`,`email`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=12006 ;
In the DB named scottse1_lifestyle_test
CREATE TABLE IF NOT EXISTS `tbl_customers_contact_types` (
`ContactId` int(4) NOT NULL DEFAULT '0',
`TypeId` int(5) NOT NULL DEFAULT '0',
PRIMARY KEY (`ContactId`,`TypeId`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
I need to:
UPDATE crmalpha.contacts
SET type = scottse1_lifestyle_test.tbl_customers_contact_types.TypeID
WHERE scottse1_lifestyle_test.tbl_customers_contact_types.ContactId = crmalpha.contacts.id
This causes the following error:
#1054 - Unknown column 'scottse1_lifestyle_test.tbl_customers_contact_types.ContactId' in 'where clause'
What am I doing wrong?
EDIT
Solution was:
UPDATE crmalpha.contacts c
JOIN scottse1_lifestyle_test.tbl_customers_contact_types t
ON t.ContactId = c.id
SET c.type = t.TypeId
You have to select the table in commaseperated way:
UPDATE CRMALPHA.contacts, scottse1_lifestyle_test.tbl_customers_contact_types
SET Type = scottse1_lifestyle_test.tbl_customers_contact_types.TypeID
WHERE scottse1_lifestyle_test.tbl_customers_contact_types.ContactId = CRMALPHA.contacts.id

MySQL - Counting a count?

I'm trying to aggregate some data I've pulled from my MySQL db.
Query I'm using is:
SELECT `PUID`,`DROID_V`,`SIG_V`,`SPEED`,
COUNT(distinct IF(sourcelist.hasExtension=1,NAME,NULL)) as Ext,
COUNT(distinct IF(sourcelist.hasExtension=0,NAME,NULL)) as NoExt,
COUNT(distinct NAME) as `All`
FROM sourcelist, main_small
WHERE sourcelist.SourcePUID = 'My_Variable' AND main_small.NAME = sourcelist.SourceFileName
GROUP BY `PUID`,`DROID_V`,`SIG_V`,`SPEED` ORDER BY `DROID_V` ASC, `SIG_V` ASC, `SPEED`
And I wondered if there was a way of counting this result, so I can make a new table that would show me something like:
Every distinct PUID, (count of distinct DROID_V), (count of distinct Sig_V), (SUM of total hits for NAME) WHERE sourcelist.SourcePUID = 'My_Variable' AND main_small.NAME = sourcelist.SourceFileName
As you can see, I'm really not very good at SQL!
Source table:
CREATE TABLE `t1` (
`DROID_V` int(1) DEFAULT NULL,
`Sig_V` varchar(7) DEFAULT NULL,
`SPEED` varchar(4) DEFAULT NULL,
`ID` varchar(7) DEFAULT NULL,
`PARENT_ID` varchar(10) DEFAULT NULL,
`URI` varchar(10) DEFAULT NULL,
`FILE_PATH` varchar(68) DEFAULT NULL,
`NAME` varchar(17) DEFAULT NULL,
`METHOD` varchar(10) DEFAULT NULL,
`STATUS` varchar(14) DEFAULT NULL,
`SIZE` int(10) DEFAULT NULL,
`TYPE` varchar(10) DEFAULT NULL,
`EXT` varchar(4) DEFAULT NULL,
`LAST_MODIFIED` varchar(10) DEFAULT NULL,
`EXTENSION_MISMATCH` varchar(32) DEFAULT NULL,
`MD5_HASH` varchar(10) DEFAULT NULL,
`FORMAT_COUNT` varchar(10) DEFAULT NULL,
`PUID` varchar(15) DEFAULT NULL,
`MIME_TYPE` varchar(24) DEFAULT NULL,
`FORMAT_NAME` varchar(10) DEFAULT NULL,
`FORMAT_VERSION` varchar(10) DEFAULT NULL,
`INDEX` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`INDEX`)
) ENGINE=MyISAM AUTO_INCREMENT=960831 DEFAULT CHARSET=utf8
example records:
5;"v37";"slow";"10266";;"file:";"V1-FL425817.tif";"V1-FL425817.tif";"BINARY_SIG";"MultipleIdenti";"20603284";"FILE";"tif";"2008-11-03";;;;"fmt/7";"image/tiff";"Tagged Ima";"3";"191977"
5;"v37";"slow";"10268";;"file:";"V1-FL425817.tif";"V1-FL425817.tif";"BINARY_SIG";"MultipleIdenti";"20603284";"FILE";"tif";"2008-11-03";;;;"fmt/8";"image/tiff";"Tagged Ima";"4";"191978"
5;"v37";"slow";"10269";;"file:";"V1-FL425817.tif";"V1-FL425817.tif";"BINARY_SIG";"MultipleIdenti";"20603284";"FILE";"tif";"2008-11-03";;;;"fmt/9";"image/tiff";"Tagged Ima";"5";"191979"
5;"v37";"slow";"10270";;"file:";"V1-FL425817.tif";"V1-FL425817.tif";"BINARY_SIG";"MultipleIdenti";"20603284";"FILE";"tif";"2008-11-03";;;;"fmt/10";"image/tiff";"Tagged Ima";"6";"191980"
Sure just do something like
Select Count(*) From (Select * From SomeTable) adummynamesoSqlParserDoesntgetupset
so put your query in parentheses after FROM give it a unique name, and you can treat it like a table or a view.