Join two tables where one table name is inside the other table - mysql

I am registering various properties in the property table. Depending on the type of property, three new tables namely apartment, villa, land is used to store specific data. So what I have is the a master table which holds property URL, Property type, Ref table name (any of the three sub table name - apartment, villa, land) and the ref id which is the primary autoincrement key of the sub tables.
I tried the three seperated select query and Union of the result. The drawback is that the results will be mostly from the first table name uses among the three.
function getMyProperty() {
$tables = $this->getPropertyTables();
$result = array();
foreach ($tables as $key => $table) {
$this->db->select('a.main_heading, a.sub_heading, a.location, a.about_property, a.property_price, a.available_from, p.property_url');
$this->db->from('property p');
$this->db->join($table . ' a', 'p.ref_id = a.id');
$this->db->where('p.posted_by', $this->session->user_id);
$this->db->where('p.ref_table', $this->db->dbprefix($table));
$query = $this->db->get();
$res = $query->result();
$result = array_merge($result, $res);
}
return $result;
}
DB SCHEMA
CREATE TABLE `apartment` (
`id` int(11) NOT NULL,
`main_heading` varchar(256) NOT NULL,
`sub_heading` text NOT NULL,
`build_up_area` int(11) NOT NULL,
`carpet_area` int(11) NOT NULL,
`no_of_bedrooms` int(11) NOT NULL,
`bathrooms` int(11) NOT NULL,
`available_from` date NOT NULL,
`furnishing` varchar(256) NOT NULL,
`facing` varchar(100) NOT NULL,
`flooring` varchar(256) NOT NULL,
`parking` varchar(256) NOT NULL,
`width_of_facing_road` varchar(100) NOT NULL,
`property_age` int(11) NOT NULL,
`property_price` decimal(16,2) NOT NULL DEFAULT '0.00',
`address` text NOT NULL,
`about_property` text NOT NULL,
`location` varchar(256) NOT NULL,
`amenities` text NOT NULL,
`owner_name` varchar(256) NOT NULL,
`owner_email` varchar(256) NOT NULL,
`owner_phone` varchar(100) NOT NULL,
`active` enum('Y','N') NOT NULL DEFAULT 'Y'
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT;
INSERT INTO `apartment` (`id`, `main_heading`, `sub_heading`, `build_up_area`, `carpet_area`, `no_of_bedrooms`, `bathrooms`, `available_from`, `furnishing`, `facing`, `flooring`, `parking`, `width_of_facing_road`, `property_age`, `property_price`, `address`, `about_property`, `location`, `amenities`, `owner_name`, `owner_email`, `owner_phone`, `active`) VALUES
(2, 'My Appartment', 'Place', 255, 400, 4, 4, '2019-08-08', 'semi', 'north', 'vitrified', '2', '15', 15, '15.00', 'ghkgkgk', 'jkhjkhjk', 'Kochi', '', 'Agent', 'abc#edg.com', '9876543210', 'Y'),
(3, 'My Appartment 2', 'Test', 255, 400, 4, 4, '2019-08-08', 'semi', 'north', 'vitrified', '2', '15', 15, '15.00', 'ghkgkgk', 'jkhjkhjk', 'Kochi', '', 'Agent', 'abc#edg.com', '9876543210', 'Y');
CREATE TABLE `land` (
`id` int(11) NOT NULL,
`main_heading` varchar(256) NOT NULL,
`sub_heading` text NOT NULL,
`plot_area` int(11) NOT NULL,
`gated_colony` int(11) NOT NULL,
`open_sides` int(11) NOT NULL,
`available_from` date NOT NULL,
`dimensions` varchar(256) NOT NULL,
`facing` varchar(100) NOT NULL,
`boundary_wall` varchar(256) NOT NULL,
`parking` varchar(256) NOT NULL,
`width_of_facing_road` varchar(100) NOT NULL,
`property_age` int(11) NOT NULL,
`property_price` decimal(16,2) NOT NULL DEFAULT '0.00',
`address` text NOT NULL,
`about_property` text NOT NULL,
`location` varchar(256) NOT NULL,
`owner_name` varchar(256) NOT NULL,
`owner_email` varchar(256) NOT NULL,
`owner_phone` varchar(100) NOT NULL,
`active` tinyint(4) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT;
CREATE TABLE `property` (
`property_id` int(11) NOT NULL,
`posted_by` int(11) NOT NULL,
`post_type` enum('RENT','SELL','LEASE') NOT NULL,
`property_type` enum('VILLA','APARTMENT','LAND') NOT NULL,
`property_url` varchar(50) NOT NULL,
`ref_table` varchar(50) NOT NULL DEFAULT '',
`ref_id` int(11) NOT NULL DEFAULT '0',
`posted_on` date NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT;
INSERT INTO `property` (`property_id`, `posted_by`, `post_type`, `property_type`, `property_url`, `ref_table`, `ref_id`, `posted_on`) VALUES
(4, 1, 'SELL', 'VILLA', 'lyohlp', 'villa', 2, '2019-08-05'),
(5, 1, 'SELL', 'APARTMENT', 'cvbdit', 'apartment', 2, '2019-08-05'),
(6, 2, 'SELL', 'APARTMENT', 'qwerty', 'apartment', 3, '2019-08-05'),
(7, 3, 'RENT', 'VILLA', 'asdfgh', 'villa', 3, '2019-08-05');
CREATE TABLE `villa` (
`id` int(11) NOT NULL,
`main_heading` varchar(256) NOT NULL,
`sub_heading` text NOT NULL,
`build_up_area` int(11) NOT NULL,
`carpet_area` int(11) NOT NULL,
`no_of_bedrooms` int(11) NOT NULL,
`bathrooms` int(11) NOT NULL,
`available_from` date NOT NULL,
`furnishing` varchar(256) NOT NULL,
`facing` varchar(100) NOT NULL,
`flooring` varchar(256) NOT NULL,
`total_area` varchar(256) NOT NULL,
`width_of_facing_road` varchar(100) NOT NULL,
`property_age` int(11) NOT NULL,
`property_price` decimal(16,2) NOT NULL DEFAULT '0.00',
`address` text NOT NULL,
`about_property` text NOT NULL,
`location` varchar(256) NOT NULL,
`amenities` text NOT NULL,
`owner_name` varchar(256) NOT NULL,
`owner_email` varchar(256) NOT NULL,
`owner_phone` varchar(100) NOT NULL,
`active` enum('Y','N') NOT NULL DEFAULT 'Y'
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT;
INSERT INTO `villa` (`id`, `main_heading`, `sub_heading`, `build_up_area`, `carpet_area`, `no_of_bedrooms`, `bathrooms`, `available_from`, `furnishing`, `facing`, `flooring`, `total_area`, `width_of_facing_road`, `property_age`, `property_price`, `address`, `about_property`, `location`, `amenities`, `owner_name`, `owner_email`, `owner_phone`, `active`) VALUES
(2, 'My Villa', 'Kakkanad', 54, 5, 4, 4, '2019-08-06', 'semi', 'west', 'not-vitrified', '111', '10', 0, '12.00', 'fhgfgh', 'ghfghf', 'Kochi', 'car_parking,water_supply,garden,fitness_center,shower,fridge', 'dfdfdf', 'abc#edg.com', '9876543210', 'Y'),
(3, 'My Villa 2', 'Place', 54, 5, 4, 4, '2019-08-06', 'semi', 'west', 'not-vitrified', '111', '10', 0, '12.00', 'fhgfgh', 'ghfghf', 'Kochi', 'car_parking,water_supply,garden,fitness_center,shower,fridge', 'dfdfdf', 'abc#edg.com', '9876543210', 'Y');
ALTER TABLE `apartment`
ADD PRIMARY KEY (`id`);
ALTER TABLE `land`
ADD PRIMARY KEY (`id`);
ALTER TABLE `property`
ADD PRIMARY KEY (`property_id`),
ADD KEY `ref_id` (`ref_id`);
ALTER TABLE `villa`
ADD PRIMARY KEY (`id`);
ALTER TABLE `apartment`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
ALTER TABLE `land`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
ALTER TABLE `property`
MODIFY `property_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=8;
ALTER TABLE `villa`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
I expect result based on the decreasing of post date irrespective of the order of the table I provided.

As we know only one of the type can be mapped with the property.
So data will be generated from one table(which store details of that property type) only, other tables will produce null.
A great way to pick data from multiple columns if only one of them is not null, is using CONCAT_WS or COALESCE.
SELECT
P.property_id, P.property_url,
CONCAT_WS('', V.main_heading, A.main_heading, L.main_heading) AS main_heading,
CONCAT_WS('', V.sub_heading, A.sub_heading, L.sub_heading) AS sub_heading,
CONCAT_WS('', V.location, A.location, L.location) AS location,
CONCAT_WS('', V.about_property, A.about_property, L.about_property) AS about_property,
CONCAT_WS('', V.property_price, A.property_price, L.property_price) AS property_price,
CONCAT_WS('', V.available_from, A.available_from, L.available_from) AS available_from,
P.posted_on
FROM property P
LEFT JOIN villa V ON P.ref_table = 'villa' AND P.ref_id = V.id
LEFT JOIN apartment A ON P.ref_table = 'apartment' AND P.ref_id = A.id
LEFT JOIN land L ON P.ref_table = 'land' AND P.ref_id = L.id
ORDER BY P.posted_on DESC;
Using COALESCE at place of CONCAT_WS would be like:
COALESCE(V.main_heading, A.main_heading, L.main_heading) AS main_heading
Reference: MySQL Function: COALESCE, MySQL Function: CONCAT_WS

You can integrate the following query in CI instead of looping in php. It provides single set array.
SELECT
a.*,
b.id,
c.id,
d.id
FROM
`property` AS a
LEFT JOIN `apartment` AS b
ON a.`ref_id` = b.id
AND a.`ref_table` = 'apartment'
LEFT JOIN `land` AS c
ON a.`ref_id` = c.id
AND a.`ref_table` = 'land'
LEFT JOIN `villa` AS d
ON a.`ref_id` = d.id
AND a.`ref_table` = 'villa'
ORDER BY a.`posted_by` DESC ;
Here, joining tables respective of constant table name and other fields will return null.Those conditions can map in PHP code.
Note : add necessary columns in select what you needed.
add this condition too : $this->db->where('p.posted_by', $this->session->user_id); in query

Related

Mysql join multiple tables with one select phrase

http://sqlfiddle.com/#!9/708aef/8/0
I have an table called mmsusbribers where i store information from users.
Then i have 3 other tables: driftinfo_subscriber_operator_lookup, driftinfo_subscriber_reseller_lookup and driftinfo_subscriber_server_lookup.
I want to join the tables together all of them in one select.
Tables look like this:
CREATE TABLE IF NOT EXISTS `mmsubscribers` (
`id` int(11) NOT NULL,
`email` varchar(50) DEFAULT NULL,
`name` varchar(50) DEFAULT NULL,
`hash` varchar(100) DEFAULT NULL,
`status` varchar(50) DEFAULT NULL,
`listid` int(11) DEFAULT NULL,
`phone` varchar(50) DEFAULT NULL,
`login` varchar(50) DEFAULT NULL,
`pass` varchar(50) DEFAULT NULL,
`language` varchar(50) DEFAULT NULL,
`orgname` varchar(75) DEFAULT NULL,
`orgadmin` int(11) DEFAULT NULL,
`domain` varchar(150) DEFAULT NULL,
`organizationId` int(11) DEFAULT NULL,
`number` varchar(15) DEFAULT NULL,
`department` varchar(50) DEFAULT NULL,
`server` varchar(20) DEFAULT NULL,
`reseller` varchar(75) DEFAULT NULL,
`operators` varchar(50) DEFAULT NULL,
`subscriber_type` int(11) DEFAULT NULL
) ENGINE=InnoDB AUTO_INCREMENT=166629 DEFAULT CHARSET=utf8;
INSERT INTO `mmsubscribers` (`id`, `email`, `name`, `hash`, `status`,
`listid`, `phone`, `login`, `pass`, `language`, `orgname`, `orgadmin`,
`domain`, `organizationId`, `number`, `department`, `server`, `reseller`,
`operators`, `subscriber_type`) VALUES
(13, 'nils#gmail.com', 'Nils Nissesson', NULL, 'inactive', 2, '+4612312313',
'user1', 'user1', 'SV', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'Reseller1',
NULL, NULL),
(15, 'nils#hotmail.com', 'Nils Karlsson', 'b5q8gelmyvp4gu9sgntgvzkha0u', 'active', 2, '+47741741109874', NULL, NULL, 'EN', '', NULL, NULL, NULL, NULL, NULL, '', '', '', NULL),
(17, 'test#testing.com', 'Test Karlsson', 'mdpte4uhkvqzew4n2megoa4qk7k', 'active', 2, '+4482798273798', NULL, NULL, 'SV', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
(18, 'test123#testdomain.se', 'Herr Vincze', 'mhw81k96liwlfj8lkyvu2rdr9y', 'inactive', 2, '', NULL, NULL, 'SV', '', NULL, '', NULL, '', '', '', '', '', NULL),
(146996, 'nils.nils#nils.se', 'Nils Dolk', 'dd07c78e2fa7487b283f6c4dbff7ec0fc448a4', 'active', 3, '', NULL, NULL, '', 'Test', 1, 'nils.se', 6721, '468123123454', 'Sälj', '185.XX.124.162', 'Reseller56', 'STH-UNO', 4),
(149277, 'bo#bosse.com', 'Bo Holgersson', 'c557202473aef551d410a00d2b1be3075e8d7e1fe', 'active', 3, '', NULL, NULL, '', 'Test', 1, 'bo.se', 6578, '4653643232436', 'Företagsförsäljning', '185.39.124.154', 'Reseller1', 'STB-uno', 4),
(149824, 'support#nisse.no', 'testar', '9c5f161459236d5d216c48a47d0c2aecf1', 'active', 3, '', NULL, NULL, '', 'Test', 1, 'bo.se', 6578, '4654170399', '', '185.XX.124.162', 'Reseller1', 'Tele2', 4);
First table witch i want to do the join to:
CREATE TABLE IF NOT EXISTS `driftinfo_subscriber_operator_lookup` (
`id` int(11) NOT NULL,
`drifinfo_problem_id` int(11) DEFAULT NULL,
`operator` varchar(75) DEFAULT NULL
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
--
-- Dumpning av Data i tabell `driftinfo_subscriber_operator_lookup`
--
INSERT INTO `driftinfo_subscriber_operator_lookup` (`id`, `drifinfo_problem_id`, `operator`) VALUES
(1, 4, 'Weblink'),
(4, 10, 'Tele2');
Second table:
CREATE TABLE IF NOT EXISTS `driftinfo_subscriber_reseller_lookup` (
`id` int(11) NOT NULL,
`drifinfo_problem_id` int(11) DEFAULT NULL,
`reseller` varchar(75) DEFAULT NULL
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
--
-- Dumpning av Data i tabell `driftinfo_subscriber_reseller_lookup`
--
INSERT INTO `driftinfo_subscriber_reseller_lookup` (`id`, `drifinfo_problem_id`, `reseller`) VALUES
(1, 4, 'Reseller1'),
(2, 4, 'Reseller2'),
(5, 10, 'Reseller3'),
(6, 10, 'BestReseller'),
(7, 10, 'BadReseller');
Third table:
CREATE TABLE IF NOT EXISTS `driftinfo_subscriber_server_lookup` (
`id` int(11) NOT NULL,
`drifinfo_problem_id` int(11) DEFAULT NULL,
`server` varchar(50) DEFAULT NULL
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
--
-- Dumpning av Data i tabell `driftinfo_subscriber_server_lookup`
--
INSERT INTO `driftinfo_subscriber_server_lookup` (`id`, `drifinfo_problem_id`, `server`) VALUES
(1, 4, '185.XX.124.162'),
(8, 10, '172.XX.129.20'),
(9, 10, '172.XX.129.21');
My last table:
CREATE TABLE IF NOT EXISTS `driftinfo_problem` (
`id` int(11) NOT NULL,
`active` varchar(11) DEFAULT NULL,
`date` date DEFAULT NULL,
`omrade` varchar(75) DEFAULT NULL,
`soluno_staging_message` varchar(750) DEFAULT NULL,
`heading` varchar(100) DEFAULT NULL,
`ingress` varchar(750) DEFAULT NULL,
`image` varchar(1500) DEFAULT NULL,
`text` varchar(3000) DEFAULT NULL,
`beskrivning` varchar(250) DEFAULT NULL,
`user_owner` varchar(75) DEFAULT NULL,
`estimate_finished_date` date DEFAULT NULL,
`language` varchar(50) DEFAULT NULL,
`time` time DEFAULT NULL,
`estimate_finished_time` time DEFAULT NULL
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8;
--
-- Dumpning av Data i tabell `driftinfo_problem`
--
INSERT INTO `driftinfo_problem` (`id`, `active`, `date`, `omrade`, `soluno_staging_message`, `heading`, `ingress`, `image`, `text`, `beskrivning`, `user_owner`, `estimate_finished_date`, `language`, `time`, `estimate_finished_time`) VALUES
(2, 'No', '2018-04-18', 'Test Problem', NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2018-04-18', NULL, '09:04:00', '16:00:00'),
(3, 'No', '2018-04-27', 'Operatör tysta samtal', NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2018-04-27', NULL, '11:35:00', '14:30:00'),
(4, 'No', '2018-05-16', 'Operator driftstörning', NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2018-05-16', NULL, '11:20:00', '14:00:00'),
(5, 'No', '2018-05-17', 'Operator driftstörning', NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2018-05-17', NULL, '14:30:00', '17:00:00'),
(6, 'No', '2018-05-18', 'Internet problem', NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2018-05-18', NULL, '16:00:00', '18:00:00'),
(7, 'No', '2018-05-25', 'Operator driftstörning', NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2018-05-25', NULL, '14:30:00', '17:00:00'),
(8, 'No', '2018-05-28', 'Operator routing problem', NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2018-05-29', NULL, '16:00:00', '12:00:00'),
(10, 'Yes', '2018-05-31', 'Operator Business störning', NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2018-05-31', NULL, '10:00:00', '14:00:00');
SQL Fiddle
I need to do an combination of these 3 selects into 1 select if possible.
Select1 operator:
SELECT
mmsubscribers.email,
driftinfo_problem.active,
driftinfo_problem.id,
mmsubscribers.reseller,
mmsubscribers.operators,
mmsubscribers.server
FROM mmsubscribers
INNER JOIN driftinfo_subscriber_operator_lookup ON mmsubscribers.operators = driftinfo_subscriber_operator_lookup.`operator`
INNER JOIN driftinfo_problem ON driftinfo_subscriber_operator_lookup.drifinfo_problem_id = driftinfo_problem.id
WHERE driftinfo_problem.active = 'Yes'
Select2 reseller:
SELECT
mmsubscribers.email,
driftinfo_problem.active,
driftinfo_problem.id,
mmsubscribers.reseller,
mmsubscribers.operators,
mmsubscribers.server
FROM mmsubscribers
INNER JOIN driftinfo_subscriber_reseller_lookup ON mmsubscribers.reseller = driftinfo_subscriber_reseller_lookup.reseller
INNER JOIN driftinfo_problem ON driftinfo_subscriber_reseller_lookup.drifinfo_problem_id = driftinfo_problem.id
Select3 server:
SELECT
mmsubscribers.email,
driftinfo_problem.active,
driftinfo_problem.id,
mmsubscribers.reseller,
mmsubscribers.operators,
mmsubscribers.server
FROM mmsubscribers
INNER JOIN driftinfo_subscriber_server_lookup ON mmsubscribers.server = driftinfo_subscriber_server_lookup.server
INNER JOIN driftinfo_problem ON driftinfo_subscriber_server_lookup.drifinfo_problem_id = driftinfo_problem.id
Expected output that i woul like to get is:
email active id reseller operators server
nils#gmail.com No 4 Reseller1 (null) (null)
bo#bosse.com No 4 Reseller1 STB-uno 185.39.124.154
support#nisse.no No 4 Reseller1 Tele2 185.XX.124.162
nils.nils#nils.se No 4 Reseller56 STH-UNO 185.XX.124.162
support#nisse.no No 4 Reseller1 Tele2 185.XX.124.162
support#nisse.no Yes 10 Reseller1 Tele2 185.XX.124.162
SELECT
mmsubscribers.email,
driftinfo_problem.active,
driftinfo_problem.id,
mmsubscribers.reseller,
mmsubscribers.operators,
mmsubscribers.server
FROM mmsubscribers
INNER JOIN driftinfo_subscriber_operator_lookup ON mmsubscribers.operators = driftinfo_subscriber_operator_lookup.`operator`
INNER JOIN driftinfo_problem ON driftinfo_subscriber_operator_lookup.drifinfo_problem_id = driftinfo_problem.id
WHERE driftinfo_problem.active = 'Yes'
union all
SELECT
mmsubscribers.email,
driftinfo_problem.active,
driftinfo_problem.id,
mmsubscribers.reseller,
mmsubscribers.operators,
mmsubscribers.server
FROM mmsubscribers
INNER JOIN driftinfo_subscriber_reseller_lookup ON mmsubscribers.reseller = driftinfo_subscriber_reseller_lookup.reseller
INNER JOIN driftinfo_problem ON driftinfo_subscriber_reseller_lookup.drifinfo_problem_id = driftinfo_problem.id
union all
SELECT
mmsubscribers.email,
driftinfo_problem.active,
driftinfo_problem.id,
mmsubscribers.reseller,
mmsubscribers.operators,
mmsubscribers.server
FROM mmsubscribers
INNER JOIN driftinfo_subscriber_server_lookup ON mmsubscribers.server = driftinfo_subscriber_server_lookup.server
INNER JOIN driftinfo_problem ON driftinfo_subscriber_server_lookup.drifinfo_problem_id = driftinfo_problem.id;

MySQL: Joining 3 tables doesn't return all results from 3rd Join

Goal: When given a user_id, retrieve the last 2 orders, with payment information, and all the items inside the order.
Query:
SELECT
PO.id,
PO.id AS order_id,
PO.user_id,
PO.deliveryaddress_id,
PO.delivery_type,
PO.store_id,
PO.placed_by,
PO.orderplaced_ts AS order_timestamp,
POP.subtotal AS order_subtotal,
POP.tax AS order_tax,
POP.secondary_tax AS order_secondary_tax,
POP.soda_tax AS order_soda_tax,
POP.delivery_fee AS order_delivery_fee,
POP.tip AS order_tip,
POP.discount AS order_discount,
POP.total AS order_total,
POP.payment_method,
POP.payment_details,
POM.*
FROM `orders` AS PO
JOIN `order_payments` AS POP
ON PO.id = POP.order_id
JOIN`order_items` AS POM
ON PO.id = POM.order_id
WHERE
PO.user_id = 12345
AND
PO.order_status != 'Cancelled'
AND
PO.order_status != 'Pending'
AND
POP.payment_collected = '1'
GROUP BY PO.id DESC
The result that I'm current receiving is only retrieving the first record from order_items table, which isn't correct. I'm attempting to retrieve ALL rows from order_items
Here is data set
CREATE TABLE `orders` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`deliveryaddress_id` int(11) NOT NULL,
`billingaddress_id` int(11) NOT NULL,
`delivery_type` enum('D','P') NOT NULL COMMENT 'D: Delivery; P: Pickup;',
`store_id` int(11) NOT NULL,
`placed_by` int(11) NOT NULL,
`ordercreated_ts` datetime NOT NULL,
`orderplaced_ts` datetime NOT NULL,
`orderread_ts` datetime NOT NULL,
`orderfulfilled_ts` datetime NOT NULL,
`order_status` enum('','Cancelled','Pending') NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`)
) ENGINE=MyISAM AUTO_INCREMENT=5443062 DEFAULT CHARSET=latin1;
CREATE TABLE `order_payments` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`order_id` int(11) NOT NULL,
`subtotal` decimal(9,2) NOT NULL,
`tax` decimal(9,2) NOT NULL,
`secondary_tax` decimal(9,2) NOT NULL,
`soda_tax` decimal(9,2) NOT NULL,
`delivery_fee` decimal(9,2) NOT NULL,
`tip` decimal(9,2) NOT NULL,
`discount` decimal(9,2) NOT NULL,
`total` decimal(9,2) NOT NULL,
`payment_method` enum('Level Up','Credit Card','Cash','House Account') NOT NULL,
`payment_details` varchar(150) DEFAULT NULL,
`payment_collected` enum('0','1') NOT NULL DEFAULT '0' COMMENT '0: payment not collected; 1: payment collected;',
PRIMARY KEY (`id`),
KEY `order_id` (`order_id`),
KEY `user_id` (`user_id`)
) ENGINE=MyISAM AUTO_INCREMENT=5277852 DEFAULT CHARSET=latin1;
CREATE TABLE `order_items` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`order_id` int(11) NOT NULL,
`menuitem_id` int(11) NOT NULL,
`quantity` int(11) NOT NULL,
`whofor` varchar(50) DEFAULT NULL,
`choppingpreference` varchar(50) DEFAULT NULL,
`in_a_wrap` varchar(50) DEFAULT NULL,
`dressingpreference` varchar(50) DEFAULT NULL,
`includebread` tinyint(1) DEFAULT NULL,
`specialrequest` text,
`customizations` text,
`price` decimal(9,2) NOT NULL,
`fav_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `order_id` (`order_id`)
) ENGINE=MyISAM AUTO_INCREMENT=9647592 DEFAULT CHARSET=latin1;
INSERT INTO `order_items` (`id`, `order_id`, `menuitem_id`, `quantity`, `whofor`, `choppingpreference`, `in_a_wrap`, `dressingpreference`, `includebread`, `specialrequest`, `customizations`, `price`, `fav_id`)
VALUES
(9647591, 5443021, 451, 1, '', '', NULL, '', 0, '', '[]', 1.99, 0),
(9647581, 5443021, 43, 1, 'Alex', 'yes', NULL, 'yes', 0, 'This is a special request', '{\"45\":1,\"80\":1,\"93\":1}', 14.86, 0);
INSERT INTO `orders` (`id`, `user_id`, `deliveryaddress_id`, `billingaddress_id`, `delivery_type`, `store_id`, `placed_by`, `ordercreated_ts`, `orderplaced_ts`, `orderread_ts`, `orderfulfilled_ts`, `order_status`)
VALUES
(5443021, 12345, 0, 0, 'D', 6, 0, '2017-08-17 16:35:15', '2017-08-17 16:36:13', '0000-00-00 00:00:00', '0000-00-00 00:00:00', '');
INSERT INTO `order_payments` (`id`, `user_id`, `order_id`, `subtotal`, `tax`, `secondary_tax`, `soda_tax`, `delivery_fee`, `tip`, `discount`, `total`, `payment_method`, `payment_details`, `payment_collected`)
VALUES
(5277851, 0, 5443021, 16.85, 1.50, 0.00, 0.00, 1.99, 3.03, 0.00, 20.34, 'Credit Card', '1647057284', '1');
and sqlfiddle of same: http://www.sqlfiddle.com/#!9/89024b/7
Try to replace the aggregation (GROUP BY) with ORDER BY. Currently you aggregate by po.id which is unique for each order.

MYSQL how to choose one of unit price

i have 3 tables
CREATE TABLE IF NOT EXISTS `items` (
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`category` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`supplier_id` int(11) DEFAULT NULL,
`item_number` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`product_id` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`description` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`size` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`tax_included` int(1) NOT NULL DEFAULT '0',
`cost_price` decimal(23,10) NOT NULL,
`unit_price` decimal(23,10) NOT NULL,
`promo_price` decimal(23,10) DEFAULT NULL,
`start_date` date DEFAULT NULL,
`end_date` date DEFAULT NULL,
`reorder_level` decimal(23,10) DEFAULT NULL,
`item_id` int(10) NOT NULL,
`allow_alt_description` tinyint(1) NOT NULL,
`is_serialized` tinyint(1) NOT NULL,
`image_id` int(10) DEFAULT NULL,
`override_default_tax` int(1) NOT NULL DEFAULT '0',
`is_service` int(1) NOT NULL DEFAULT '0',
`deleted` int(1) NOT NULL DEFAULT '0',
`items_batang_6` tinyint(1) NOT NULL,
`items_batang_55` tinyint(1) NOT NULL,
`items_batang_3` tinyint(1) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=255 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `items` (`name`, `category`, `supplier_id`, `item_number`, `product_id`, `description`, `size`, `tax_included`, `cost_price`, `unit_price`, `promo_price`, `start_date`, `end_date`, `reorder_level`, `item_id`, `allow_alt_description`, `is_serialized`, `image_id`, `override_default_tax`, `is_service`, `deleted`, `items_batang_6`, `items_batang_55`, `items_batang_3`) VALUES
('PC 60 K', 'Bahan Profil', NULL, '00000000001', 'PC 60 K', '', '', 0, '250.0000000000', '235000.0000000000', NULL, NULL, NULL, NULL, 1, 0, 0, NULL, 0, 0, 0, 0, 0, 0),
('PC 60 DY', 'Bahan Profil', NULL, '00000000002', 'AGK 02B', '', '', 0, '100.0000000000', '50000.0000000000', NULL, NULL, NULL, NULL, 6, 0, 0, NULL, 0, 0, 0, 0, 0, 0)
CREATE TABLE IF NOT EXISTS `price_tiers` (
`id` int(10) NOT NULL,
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=35 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `price_tiers` (`id`, `name`) VALUES
(1, 'Jendela Kaca Mati Single'),
(2, 'Jendela Kaca Mati Double'),
(3, ' Jendela Swing Single KN KR'),
(4, 'Jendela Swing Double J106')
CREATE TABLE IF NOT EXISTS `items_tier_prices` (
`tier_id` int(10) NOT NULL,
`item_id` int(10) NOT NULL,
`unit_price` decimal(23,10) DEFAULT '0.0000000000',
`percent_off` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
INSERT INTO `items_tier_prices` (`tier_id`, `item_id`, `unit_price`, `percent_off`) VALUES
(1, 1, '200000.0000000000', NULL),
(4, 6, '40000.0000000000', NULL);
What I am trying to accomplish is to display ALL list of items which is connected to price_tiers.name='Jendela Swing Double J106'.
If it doesn't have items_tier_prices.unit_price, column price
will display items.unit_price, but if it has items_tier_prices.unit_price, query will display items_tier_prices.unit_price. so the default to be displayed is items.unit_price. i want to be like this when i have data item_id 6 on items_tier_prices:
item_id price
==============================
1 235000
6 40000
but when i delete data item_id 6 on items_tier_prices:
item_id price
==============================
1 235000
6 50000
what i have tried is:
SELECT items.item_id, if(items_tier_prices.unit_price is null,items.unit_price, items_tier_prices.unit_price ) as unit_price FROM `items`
LEFT JOIN `items_tier_prices`
ON `items_tier_prices`.`item_id`=`items`.`item_id`
LEFT JOIN `price_tiers`
ON `price_tiers`.`id`=`items_tier_prices`.`tier_id`
WHERE `items`.`deleted` = 0
and price_tiers.name='Jendela Swing Double J106'
but it only display item_id 1 when i dont have data of item_id 6 in item_tier_prices
pls help.. many thanks
Currently your join before the WHERE provides (some fields added to explore):
SELECT items.item_id, if(items_tier_prices.unit_price is null,items.unit_price, items_tier_prices.unit_price ) as unit_price,
price_tiers.name,
`items`.`deleted`
FROM `items`
LEFT JOIN `items_tier_prices`
ON `items_tier_prices`.`item_id`=`items`.`item_id`
LEFT JOIN `price_tiers`
ON `price_tiers`.`id`=`items_tier_prices`.`tier_id`
Return
----------
'1', '200000.0000000000', 'Jendela Kaca Mati Single', '0'
'6', '40000.0000000000', 'Jendela Swing Double J106', '0'
Putting the where it returns:
'6', '40000.0000000000'
I do not understand where is the issue, you do not have 2 records on Jendela Swing Double J106.
Regards
Here's what I think you are trying to achieve:
You have items in a table which have a price per unit (unit_price).
IFF (if and only if) there is a relation between a tier and an item, the special price per unit is supposed to show up.
If not, use the original item's unit_price.
In your example, you have two items, IDs 1 and 6, and they are both related to some price tier. However, item #1 is tied to tier #1 and item #6 is tied to tier #4.
Since you are specifically searching for special prices only if the are from tier #4, you need to pass that information to the JOIN statement instead of the WHERE statement. That way, it's not filtered out but can be used to display different prices.
SELECT
i.item_id,
IF(pt.name IS NULL, i.unit_price, itp.unit_price) AS unit_price
FROM
items i
LEFT JOIN items_tier_prices itp
ON itp.item_id = i.item_id
LEFT JOIN price_tiers pt
ON pt.id = itp.tier_id
AND pt.name = "Jendela Swing Double J106"
WHERE i.deleted = 0
This will produce the following output:
item_id unit_price
6 40000.0000000000
1 235000.0000000000
where item #6's price is from the tier special and item #1 shows the price from the items table.

Selecting count from another table is only showing 1 row where it exists

I am trying to select a row count from another table even if it's empty, so if it's empty it just shows the number 0 but still selects the main table's rows.
Here's my sql:
SELECT training.*,
count(distinct training_transactions.training_transaction_course) as completed_training_payments
FROM training
INNER JOIN training_transactions
ON training.course_id = training_transactions.training_transaction_course
WHERE course_main = ?
AND course_enabled = 'enabled'
Training table:
CREATE TABLE IF NOT EXISTS `training` (
`course_id` int(11) NOT NULL,
`course_user` int(11) NOT NULL,
`course_main` int(11) NOT NULL,
`course_type` varchar(255) NOT NULL,
`course_name` varchar(255) NOT NULL,
`course_description` text NOT NULL,
`course_location` varchar(255) NOT NULL,
`course_duration` varchar(255) NOT NULL,
`course_fitness_type` varchar(255) NOT NULL,
`course_instructor_name` varchar(255) NOT NULL,
`course_price` int(15) NOT NULL,
`course_start_date` date NOT NULL,
`course_max_attendees` int(8) NOT NULL,
`course_accommodation` varchar(255) NOT NULL,
`course_accommodation_price` varchar(255) NOT NULL,
`course_status` varchar(50) NOT NULL,
`course_enabled` varchar(10) NOT NULL DEFAULT 'enabled',
`course_location_name` varchar(255) NOT NULL,
`course_location_street` varchar(255) NOT NULL,
`course_location_town` varchar(255) NOT NULL,
`course_location_county` varchar(255) NOT NULL,
`course_location_postcode` varchar(255) NOT NULL,
`course_location_country` varchar(255) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
--
-- Dumping data for table `training`
--
INSERT INTO `training` (`course_id`, `course_user`, `course_main`, `course_type`, `course_name`, `course_description`, `course_location`, `course_duration`, `course_fitness_type`, `course_instructor_name`, `course_price`, `course_start_date`, `course_max_attendees`, `course_accommodation`, `course_accommodation_price`, `course_status`, `course_enabled`, `course_location_name`, `course_location_street`, `course_location_town`, `course_location_county`, `course_location_postcode`, `course_location_country`) VALUES
(1, 3, 4, 'Health & Safety', 'lol', 'This is just a short description, this can be editted', '1', '13', 'lol', 'lol', 5, '1991-02-12', 4, '1', '4', 'live', 'enabled', '', '', '', '', '', 'United Kingdom'),
(2, 3, 4, 'Working at Height', 'lol', '', '1', '11', 'jkjkj', 'kjkjkj', 124, '0000-00-00', 6, '0', '', 'live', 'enabled', '', '123', '123', '123', 'WN8', 'United Kingdom'),
(3, 3, 4, 'Working at Height', 'lol', '', '1', '11', 'jkjkj', 'kjkjkj', 124, '0000-00-00', 6, '0', '', 'live', 'enabled', '', '123', '123', '123', 'WN8', 'United Kingdom');
training_transactions
CREATE TABLE IF NOT EXISTS `training_transactions` (
`training_transaction_id` int(11) NOT NULL,
`training_transaction_user` int(11) NOT NULL,
`training_transaction_course` int(11) NOT NULL,
`training_transaction_status` varchar(50) NOT NULL DEFAULT 'pending',
`training_transaction_payment_status` varchar(50) NOT NULL,
`training_transaction_cost` int(11) NOT NULL,
`training_transaction_enabled` varchar(50) NOT NULL DEFAULT 'enabled',
`training_transaction_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`training_transaction_billing_name` varchar(250) NOT NULL,
`training_transaction_billing_address1` varchar(250) NOT NULL,
`training_transaction_billing_address2` varchar(250) NOT NULL,
`training_transaction_billing_city` varchar(250) NOT NULL,
`training_transaction_billing_state` varchar(250) NOT NULL,
`training_transaction_billing_postcode` varchar(250) NOT NULL,
`training_transaction_billing_country` varchar(250) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
--
-- Dumping data for table `training_transactions`
--
INSERT INTO `training_transactions` (`training_transaction_id`, `training_transaction_user`, `training_transaction_course`, `training_transaction_status`, `training_transaction_payment_status`, `training_transaction_cost`, `training_transaction_enabled`, `training_transaction_date`, `training_transaction_billing_name`, `training_transaction_billing_address1`, `training_transaction_billing_address2`, `training_transaction_billing_city`, `training_transaction_billing_state`, `training_transaction_billing_postcode`, `training_transaction_billing_country`) VALUES
(1, 3, 1, 'pending', 'complete', 0, 'enabled', '2015-09-17 14:02:29', *removed my address*);
at the moment only the training course with id 1 is showing because a row in transactions exists how can I make all training display if it no id matches in the training_transactions?
Use LEFT JOIN instead of inner join to list all records from the table on the left of the join, plus you need to place the count() in a subquery to get all fields from the training table:
SELECT training.*, ifnull(T.transactioncount,0) as transactioncount
FROM training
LEFT JOIN (SELECT training_transaction_course, COUNT(training_transaction_course) as transactioncount FROM training_transactions GROUP BY training_transaction_course) AS T
ON training.course_id = T.training_transaction_course
WHERE course_main = ?
AND course_enabled = 'enabled'
INNER JOIN only selects records where records with join key in both tables exist.
With LEFT JOIN / RIGHT JOIN, selections can be made where records on one side don't exist; their field values will be NULL (and when counted, they should be zero but I'm not COMPLETELY sure of that)
Sometimes it is just easier to use sub-queries. Try this:
SELECT training.*,
(SELECT COUNT(distinct training_transactions.training_transaction_course)
FROM training_transactions
WHERE training.course_id = training_transactions.training_transaction_course) AS completed_training_payments
FROM training
WHERE training.course_main = ?
AND training.course_enabled = 'enabled'

Find all missing mapping table entries

I need to be able to determine all of the people that were missing from attendance in a series of meetings.
I have a solution to figure this problem out with JS on the client's computer but I think it could be done more efficiently on the server.
Table A (people) -> Table B (attendance) <- Table C(meeting)
The attendance is a mapping table of items in table A and C.
See: http://sqlfiddle.com/#!8/6db81 for the exact schema
What I want is to determine all of the meetings that people have missed. That is there is no entry for that person for that meeting in the attendance table B.
Desired output should include a minimum of the lid (user id) and mid (meeting ID).
lid, firstname, lastname, mid, meeting_title, start.
The solution in JS would be to send the results of a cross of A and C, and the results of B to the client. Then remove all of the items in B from the cross of A and C.
CREATE TABLE IF NOT EXISTS `attendance` (
`mid` bigint(20) NOT NULL,
`sid` bigint(20) DEFAULT NULL,
`entered` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`lid` varchar(64) CHARACTER SET utf8 NOT NULL,
PRIMARY KEY (`mid`,`lid`),
KEY `entered` (`entered`)
);
INSERT INTO `attendance` (`mid`, `sid`, `entered`, `lid`) VALUES
(5, NULL, '2013-12-25 21:44:27', '100'),
(5, NULL, '2013-12-25 21:44:19', '200'),
(5, NULL, '2013-12-25 21:44:21', '300'),
(9, NULL, '2013-12-26 14:49:49', '200'),
(9, NULL, '2013-12-26 07:10:34', '300');
CREATE TABLE IF NOT EXISTS `meetings` (
`mid` bigint(11) NOT NULL AUTO_INCREMENT,
`title` varchar(32) CHARACTER SET utf8 NOT NULL,
`start` datetime NOT NULL COMMENT 'registration start time',
`stop` datetime NOT NULL COMMENT 'registration stop time',
PRIMARY KEY (`mid`),
UNIQUE KEY `title` (`title`)
);
INSERT INTO `meetings` (`mid`, `title`, `start`, `stop`) VALUES
(5, 'Meeting 1', '2013-12-25 01:12:00', '2013-12-25 23:12:00'),
(9, 'Meeting 2', '2013-12-26 01:00:00', '2013-12-26 23:00:00');
CREATE TABLE IF NOT EXISTS `people` (
`sid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`lid` varchar(64) NOT NULL,
`firstname` varchar(64) NOT NULL,
`lastname` varchar(64) NOT NULL,
`title` varchar(5) DEFAULT NULL,
`address` varchar(128) DEFAULT NULL,
`city` varchar(64) DEFAULT NULL,
`state` varchar(2) DEFAULT NULL,
`zip` varchar(9) DEFAULT NULL,
`phone` varchar(12) DEFAULT NULL,
`cell` varchar(12) DEFAULT NULL,
`email` varchar(64) DEFAULT NULL,
PRIMARY KEY (`sid`),
UNIQUE KEY `sid` (`sid`),
UNIQUE KEY `lid` (`lid`)
);
INSERT INTO `people` (`sid`, `lid`, `firstname`, `lastname`, `title`, `address`, `city`, `state`, `zip`, `phone`, `cell`, `email`) VALUES
(1, '100', 'Fred', 'Jones', 'Mr.', 'Somewhere', 'City', 'AK', '12345', '123-123-1234', '123-123-1234', 'email#email.com'),
(2, '200', 'Wilma', 'Jones', 'Mrs.', '', 'City', '', '12346', '', NULL, '');
You have to join people and meetings table to get all possible combinations of meeting id and userid and then filter out only those, which are not present in attendance table.
SELECT a.lid,
b.mid
FROM people a
CROSS JOIN meetings b
WHERE NOT EXISTS (SELECT 1
FROM attendance c
WHERE c.mid = b.mid
AND c.lid = a.lid);
Fiddle