codeigniter: active record like clause not working - mysql

I'm trying to convert this mysql query to active record, but the like clause not working properly and not return any output. I don't get what I missed actually.
table schema:
tbl_batch:
CREATE TABLE `tbl_batch` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Round` varchar(5) COLLATE utf8_bin NOT NULL,
`BatchID` varchar(255) COLLATE utf8_bin NOT NULL,
`TSP` varchar(10) COLLATE utf8_bin NOT NULL,
`Slot` tinyint(1) NOT NULL,
`Trade` int(11) NOT NULL,
`StartDate` date NOT NULL,
`EndDate` date NOT NULL,
PRIMARY KEY (`BatchID`),
UNIQUE KEY `ID` (`ID`),
UNIQUE KEY `BatchID` (`BatchID`),
UNIQUE KEY `BatchID_2` (`BatchID`)
) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=utf8 COLLATE=utf8_bin
tbl_tsp_info:
CREATE TABLE `tbl_tsp_info` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`TSP` varchar(10) NOT NULL,
`Name` varchar(50) NOT NULL,
`Email` varchar(50) NOT NULL,
`Website` varchar(50) NOT NULL,
`ContactPerson` varchar(50) NOT NULL,
`ContactPhone` varchar(11) NOT NULL,
`Phone` varchar(11) NOT NULL,
`Fax` varchar(11) NOT NULL,
`Address` varchar(255) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4
tbl_instructor_info
CREATE TABLE `tbl_instructor_info` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`InstructorID` varchar(7) NOT NULL,
`Name` varchar(50) NOT NULL,
`Mobile` varchar(11) NOT NULL,
`Email` varchar(50) NOT NULL,
`Trade` int(1) NOT NULL,
`TSP` int(1) NOT NULL,
`Slot` tinyint(1) NOT NULL,
PRIMARY KEY (`ID`),
UNIQUE KEY `InstructorID` (`InstructorID`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8
MySQL Query: (Working perfectly)
SELECT BatchID
from tbl_batch
WHERE Round='7'
AND BatchID LIKE concat('%', (SELECT ShortCode FROM tbl_tsp_info WHERE id=
(SELECT TSP FROM tbl_instructor_info WHERE Email='monir.ssts#gmail.com')),'%')
Codeigniter Model:
public function get_batch_byUser($email=string) {
$this->db->select('TSP');
$this->db->from('tbl_instructor_info');
$this->db->where('email',$email);
$tsp = $this->db->get_compiled_select();
$this->db->select('ShortCode');
$this->db->from('tbl_tsp_info');
$this->db->where("`id`= ($tsp)", null, false);
$batchCode = $this->db->get_compiled_select();
$this->db->select('BatchID ');
$this->db->from('tbl_batch');
$this->db->where('round',7);
$this->db->like('BatchID', $batchCode);
$query = $this->db->get();
return $query->result();
}

I see the problem but the solution may or may not work.
Here's how to see the problem. Replace the last line of code your code return $query->result(); with
echo $this->db->get_compiled_select();
You will see
SELECT `BatchID`
FROM `tbl_batch`
WHERE `round` = 7
AND `BatchID` LIKE '%SELECT `ShortCode`\nFROM `tbl!_tsp!_info`
\nWHERE `id`= (SELECT `TSP`\nFROM `tbl!_instructor!_info`
\nWHERE `email` = \'me#example.com\')%' ESCAPE '!'
See where the wildcards characters (%) are? Not going to work.
If you change
$this->db->like('BatchID', $batchCode);
to
$this->db->like('BatchID', "($batchCode)");
The echo is this
SELECT `BatchID` FROM `tbl_batch`
WHERE `round` = 7
AND `BatchID`
LIKE '%(SELECT `ShortCode`\nFROM `tbl!_tsp!_info`
\nWHERE `id`= (SELECT `TSP`\nFROM `tbl!_instructor!_info`
\nWHERE `email` = \'me#example.com\'))%' ESCAPE '!'
I don't know if that will execute correctly - I don't have the datasets. But the syntax looks right. Right?
Sometime "Active Record" (in Codeigniter > v3.0 "Query Builder") is not the most efficient way to get what you need. Falling back to more basic methods will often be a lot less trouble.
$sql = "SELECT BatchID from tbl_batch WHERE Round='7' AND BatchID
LIKE concat('%', (SELECT ShortCode FROM tbl_tsp_info
WHERE id = (SELECT TSP FROM tbl_instructor_info
WHERE Email= ?)),'%')";
$query = $this->db->query($sql, [$email]);
return $query->result();

Related

select from two tables each with different join

Trying to run this query will not return any error but I guess there is still something wrong in it. After four minutes running it keeps elaborating:
SELECT DISTINCT azioni_row.id_az, sofferenze.Descrizione, COUNT(crediti.stato = 'aperta') as aperti, COUNT(crediti.stato = 'chiusa') as chiusi
FROM (`azioni_row`, sofferenze)
JOIN crediti ON azioni_row.id_cred=crediti.id_cre
JOIN azioni_head as ah1 ON azioni_row.id_az=ah1.id_az
JOIN azioni_head as ah2 ON ah2.id_soff = sofferenze.id_soff
GROUP BY id_az
ORDER BY `azioni_row`.`id_az` ASC
If I remove sofferenze.Descrizione from the select list and sofferenze from the FROM list it runs in a few seconds:
SELECT DISTINCT azioni_row.id_az, COUNT(crediti.stato = 'aperta') as aperti, COUNT(crediti.stato = 'chiusa') as chiusi
FROM azioni_row
JOIN crediti ON azioni_row.id_cred=crediti.id_cre
JOIN azioni_head as ah1 ON azioni_row.id_az=ah1.id_az
GROUP BY id_az
ORDER BY `azioni_row`.`id_az` ASC
I would like to show the Descrizione field but the link for it is in the head table, not in the row one. The relationship between head and row is a one to many. I store in head all the info that is not necessary to repeat for each row and the link with Descrizione is one of these fields.
EDIT:
this is the explain:
this is the create for azioni_head:
CREATE TABLE `azioni_head` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`tipo` varchar(2) NOT NULL,
`id_az` varchar(11) NOT NULL,
`id_soff` varchar(11) NOT NULL,
`id_soff_gar` varchar(11) DEFAULT NULL,
`date_from` date NOT NULL,
`date_to` date NOT NULL,
`close_why` int(11) NOT NULL,
`RGE` varchar(30) NOT NULL,
`procedente` varchar(2) NOT NULL,
`curatore` varchar(11) NOT NULL,
`legale` varchar(11) NOT NULL,
`tribunale` varchar(11) NOT NULL,
`riparto` varchar(2) NOT NULL DEFAULT '0',
`perc_worst` decimal(13,10) NOT NULL,
`perc_best` decimal(13,10) NOT NULL,
`perc_poster` decimal(13,10) NOT NULL,
`attivo_storico` decimal(65,2) NOT NULL,
`passivo_storico` decimal(65,2) NOT NULL,
`attivo_storico_comm` decimal(65,2) NOT NULL,
`passivo_storico_comm` decimal(65,2) NOT NULL,
`acconti` decimal(65,2) NOT NULL,
`acconti_comm` decimal(65,2) NOT NULL,
`numero_comm` int(11) NOT NULL,
`legali_worst` decimal(65,2) NOT NULL,
`legali_best` decimal(65,2) NOT NULL,
`manuale` tinyint(1) NOT NULL DEFAULT '0',
`created_by` int(11) NOT NULL,
`created_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1449 DEFAULT CHARSET=utf8 COMMENT='tabella testata azioni'
this for azioni_row:
CREATE TABLE `azioni_row` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_az` varchar(11) NOT NULL,
`id_cred` varchar(11) NOT NULL,
`chiesto` decimal(65,2) NOT NULL,
`ammesso` decimal(65,2) NOT NULL,
`data_ammesso` date NOT NULL,
`rango_ammesso` tinytext NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4479 DEFAULT CHARSET=utf8
and this for sofferenze
CREATE TABLE `sofferenze` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_soff` varchar(11) NOT NULL,
`Descrizione` tinytext NOT NULL,
`gruppo` int(11) NOT NULL,
`cointestazione` int(11) NOT NULL,
`port_man` tinytext NOT NULL,
`head_port_man` tinytext NOT NULL,
`note` longtext NOT NULL,
`created_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`created_by` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`),
UNIQUE KEY `id_3` (`id`),
KEY `id_2` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1716 DEFAULT CHARSET=utf8
Please provide proper CREATE statements as well as the output of:
EXPLAIN
SELECT a.id_az
, s.Descrizione
, COUNT(c.stato = 'aperta') aperti
, COUNT(c.stato = 'chiusa') chiusi
FROM azioni_row a
JOIN sofferenze s
CROSS
JOIN crediti c
ON c.id_cre = a.id_cred
JOIN azioni_head ah1
ON ah1.id_az = a.id_az
JOIN azioni_head ah2
ON ah2.id_soff = s.id_soff
GROUP
BY a.id_az
, s.Descrizione
ORDER
BY a.id_az ASC
Edit: You seem to have lots of indexes on the same column. Drop all indexes except the PRIMARY KEYs, and create the following indexes:
sofferenze: id_soff
azioni_row: try a composite index on (id_az,id_cred)
azioni_head: an index on id_soff and an index on id_az
Crediti is missing so I can't comment on that one.

Finding out if there is a daily insert into mysql table

I have this table which should be getting daily input regarding Vehicle mileage Readings.
CREATE TABLE `table_vehicle_info` (
`id` int(11) NOT NULL ,
`reg_no` varchar(50) NOT NULL,
`vehicle_type` int(11) NOT NULL,
`engine_no` varchar(50) NOT NULL DEFAULT "DDDD",
`chassis_no` varchar(50) ,
`model` int(11) DEFAULT NULL,
`picture` varchar(50) ,
`rent` double ,
`eng_power` int(11) DEFAULT NULL,
`color` varchar(12) DEFAULT NULL,
`rent_status` varchar(50) DEFAULT NULL,
`reg_city` varchar(50) DEFAULT NULL,
`location` varchar(50) DEFAULT NULL,
`sub_type` varchar(50) DEFAULT NULL,
`purchase_date` date DEFAULT NULL,
`purchase_amount` double DEFAULT NULL,
`sum_insured` double DEFAULT NULL,
`token_tax_amount` double DEFAULT NULL,
`token_period_from` date DEFAULT NULL,
`reg_placed_at` varchar(50) DEFAULT NULL,
`funded_by` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=99 DEFAULT CHARSET=latin1;
CREATE TABLE `tbl_readings` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`vehicle_id` int(11) NOT NULL,
`km_driven` int(11) NOT NULL,
`dt_of_reading` datetime NOT NULL,
`dt_of_entry` datetime NOT NULL,
`entry_user` varchar(50) NOT NULL,
PRIMARY KEY (`id`),
KEY `vehicle_id` (`vehicle_id`),
CONSTRAINT `tbl_readings_ibfk_1` FOREIGN KEY (`vehicle_id`) REFERENCES `table_vehicle_info` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=latin1;
INSERT INTO table_vehicle_info (id,reg_no,vehicle_type )
VALUES (1, "B-5484", 12 );
INSERT INTO tbl_readings VALUES (NULL,1,100,'2015-6-1',NOW(), 'user');
I want to generate a report showing which vehicle reading isn't entered daily.
You can try following query, it returns all vehicle_id from tbl_readings for which there is no next day entry.
SELECT vehicle_id
FROM `tbl_readings`
WHERE DATE(DATE_ADD(dt_of_entry,INTERVAL 1 DAY)) NOT IN
(SELECT DATE(dt_of_entry) FROM `tbl_readings`)
EDIT
Try this,
SELECT t1.vehicle_id
FROM `tbl_readings` t1
LEFT JOIN (SELECT vehicle_id,
DATE(DATE_ADD(dt_of_reading,INTERVAL -1 DAY)) as reading_date
FROM `tbl_readings`) t2
ON t1.vehicle_id = t2.vehicle_id AND t1.dt_of_reading = t2.reading_date
WHERE t2.vehicle_id IS NULL
GROUP BY t1.vehicle_id
HAVING COUNT(t1.vehicle_id) > 1;
check the fiddle

Query data from two tables does not work, query only a single tables works

Here is my export.
CREATE TABLE IF NOT EXISTS `table1` (
`order_id` int(7) NOT NULL DEFAULT '0',
`order_date` varchar(8) DEFAULT NULL,
`tkt_order_id` int(9) DEFAULT NULL,
`event_date` varchar(8) DEFAULT NULL,
`event_name` varchar(6) DEFAULT NULL,
`event_year` int(4) DEFAULT NULL,
`mail` varchar(60) NOT NULL,
`quantity` int(3) DEFAULT NULL,
`ticket_type` varchar(7) DEFAULT NULL,
`ticket_days` varchar(9) DEFAULT NULL,
`ticket_subtype` varchar(18) DEFAULT NULL,
`base` varchar(10) DEFAULT NULL,
`service` varchar(10) DEFAULT NULL,
`gross` varchar(10) DEFAULT NULL,
PRIMARY KEY (`order_id`),
UNIQUE KEY `order_id` (`order_id`) USING BTREE,
KEY `email` (`mail`,`order_date`,`event_name`,`event_year`,`quantity`,`ticket_type`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `table2` (
`mail` varchar(60) NOT NULL DEFAULT '',
`first_name` varchar(27) DEFAULT NULL,
`lastname` varchar(20) DEFAULT NULL,
`address` varchar(63) DEFAULT NULL,
`address2` varchar(38) DEFAULT NULL,
`city` varchar(27) DEFAULT NULL,
`state` varchar(22) DEFAULT NULL,
`zip` varchar(10) DEFAULT NULL,
`country` varchar(20) DEFAULT NULL,
`phone` varchar(16) DEFAULT NULL,
PRIMARY KEY (`mail`),
UNIQUE KEY `mail` (`mail`) USING BTREE,
KEY `index` (`first_name`,`lastname`,`city`,`state`,`zip`,`country`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `table1`
ADD CONSTRAINT `table1_ibfk_1` FOREIGN KEY (`mail`) REFERENCES `table2` (`mail`) ON DELETE NO ACTION ON UPDATE NO ACTION;
You forgot to include the meaningful link on the foreign key in your where-clause:
db.sales.mail = db.customers.mail
Also, use brackets to group your conditions together. Something like cond1 OR cond2 AND cond3 will probably not work as expected, so for example you could write this as (cond1 OR cond2) AND cond3.
So something like this should work:
SELECT db.customers.first_name,
db.customers.last_name,
db.customers.mail,
db.sales.event_year,
db.sales.ticket_type,
db.sales.event_name
FROM db.sales, db.customers
WHERE db.sales.mail = db.customer.mail
AND (db.sales.ticket_type = "ticket1"
OR db.sales.ticket_type = "ticket2"
OR db.sales.ticket_type = "ticket3")
AND (db.sales.event_year=2009
OR db.sales.event_year=2010)
While the above should work, it's better to write it like this (mostly for readability):
SELECT c.first_name,
c.last_name,
c.mail,
s.event_year,
s.ticket_type,
s.event_name
FROM db.sales s
INNER JOIN db.customer c ON s.mail = c.mail
WHERE s.ticket_type IN ('ticket1','ticket2','ticket3')
AND s.event_year IN (2009,2010);
Note: I simply removed the final GROUP BY in your query, since I don't know what you're trying to accomplish with that. If you use GROUP BY, it should be on at least all selected columns that are not aggregate functions (like SUM, COUNT etc.)
Use left join instead of inner join. Eg:
SELECT c.*, s.*
FROM customers c
LEFT JOIN sales s ON s.email = c.email;

Unexpected behaviour of the query

This particular query is supposed to enter the user into the database.
This query does not always insert the values of the firstname and the lastname fields along with others. firstname and lastname are empty for a few insertions and for the others its working as expected.
INSERT INTO `users` (mobile, passwordHash, firstname, lastname, ent_id, email )
VALUES ('913800341127', '678a1491514b7f1006d605e9161946b1', 'nat', 'sam', '108', NULL)
ON DUPLICATE KEY UPDATE `firstname` = VALUES(firstname),`lastname` = VALUES(lastname)
Related Info:
CREATE TABLE `users` (
`id` int(11) NOT NULL auto_increment,
`tag` varchar(5) NOT NULL default 'ind',
`username` varchar(50) default NULL,
`firstname` varchar(100) default NULL,
`lastname` varchar(100) default NULL,
`passwordhash` varchar(255) NOT NULL,
`secretq` varchar(255) default NULL,
`secreta` varchar(100) default NULL,
`email` varchar(50) default NULL,
`mobile` varchar(13) default NULL,
`last_login` datetime default NULL,
`ent_id` bigint(20) NOT NULL default '1',
`is_inactive` tinyint(1) NOT NULL COMMENT 'Whether the user is active or not',
PRIMARY KEY (`id`),
UNIQUE KEY `mobile_2` (`mobile`,`ent_id`),
UNIQUE KEY `email_2` (`email`,`ent_id`),
KEY `username` (`username`),
KEY `ent_id` (`ent_id`,`tag`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
syntax error it should be :
ON DUPLICATE KEY UPDATE firstname = 'nat',lastname = 'sam'

sql statement mysql notcorrect

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