MYSQL how to choose one of unit price - mysql

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.

Related

Select subscriptions based on user id

I have these MySQL tables where I want to store user subscriptions:
CREATE TABLE subscription (
`id` int(11) NOT NULL AUTO_INCREMENT,
`amount` decimal(19,2) DEFAULT NULL,
`created_at` datetime(6) DEFAULT NULL,
`currency` varchar(20) DEFAULT NULL,
`duration` bigint(20) DEFAULT NULL,
`end_at` datetime(6) DEFAULT NULL,
`error` varchar(200) DEFAULT NULL,
`order_id` int(11) DEFAULT NULL,
`product` varchar(20) DEFAULT NULL,
`run_at` datetime(6) DEFAULT NULL,
`start_at` datetime(6) DEFAULT NULL,
`status` varchar(20) DEFAULT NULL,
`updated_at` datetime(6) DEFAULT NULL,
`title` varchar(20) DEFAULT NULL,
`parent_transaction_id` int(11) DEFAULT NULL,
`parent_transactionId` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=23443556 DEFAULT CHARSET=latin1;
INSERT INTO subscription (`id`, `amount`, `created_at`, `currency`, `duration`, `end_at`, `error`, `order_id`, `product`, `run_at`, `start_at`, `status`, `updated_at`, `title`, `parent_transaction_id`, `parent_transactionId`) VALUES
('122', '3333.00', '2020-10-31 19:41:16.622386', 'USD', '1000', '2020-10-31 19:41:16.622386', 'error message', '122', 'error message', '2020-10-31 19:41:16.622386', '2020-10-31 19:41:16.622386', 'active', '2020-10-31 19:41:16.622386', 'title', '443', '5544');
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(255) DEFAULT NULL,
`enabled` tinyint(4) DEFAULT NULL,
`encrypted_password` varchar(255) DEFAULT NULL,
`first_name` varchar(255) DEFAULT NULL,
`last_name` varchar(255) DEFAULT NULL,
`role` varchar(25) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=153 DEFAULT CHARSET=latin1;
INSERT INTO `users` (`id`, `email`, `enabled`, `encrypted_password`, `first_name`, `last_name`, `role`) VALUES
('192', 'test#mail.com', '1', '$2a$31$ovShEKleI3Yk2vgjAIF5mO4HkGWXcTSKPMTaj7rFN4KAtlEz0f/ay', 'test', 'test', 'ROLE_CLIENT');
CREATE TABLE `orders` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`city` varchar(30) DEFAULT NULL,
`CONTENT` text DEFAULT NULL,
`country` varchar(50) DEFAULT NULL,
`created_at` datetime(6) DEFAULT NULL,
`discount` decimal(8,2) DEFAULT NULL,
`email` varchar(50) DEFAULT NULL,
`first_name` varchar(50) DEFAULT NULL,
`grand_total` decimal(8,2) DEFAULT NULL,
`item_discount` decimal(8,2) DEFAULT NULL,
`last_name` varchar(50) DEFAULT NULL,
`line1` varchar(50) DEFAULT NULL,
`line2` varchar(50) DEFAULT NULL,
`middle_name` varchar(50) DEFAULT NULL,
`mobile` varchar(15) DEFAULT NULL,
`promo` varchar(100) DEFAULT NULL,
`province` varchar(50) DEFAULT NULL,
`session_id` int(11) DEFAULT NULL,
`shipping` decimal(8,2) DEFAULT NULL,
`status` varchar(100) DEFAULT NULL,
`sub_total` decimal(8,2) DEFAULT NULL,
`tax` decimal(8,2) DEFAULT NULL,
`token` varchar(100) DEFAULT NULL,
`total` decimal(8,2) DEFAULT NULL,
`updated_at` datetime(6) DEFAULT NULL,
`user_id` int(11) DEFAULT NULL,
`phone` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=65 DEFAULT CHARSET=latin1;
INSERT INTO `orders` (`id`, `city`, `CONTENT`, `country`, `created_at`, `email`, `first_name`, `grand_total`, `item_discount`, `last_name`, `status`, `sub_total`, `tax`, `total`, `user_id`) VALUES
('122', 'city', 'test context', 'USA', '2021-05-25 12:40:23.793779', 'test#email.com', 'first name', '100', '10', 'last name', 'active', '20', '10', '200', '192');
INSERT INTO `orders` (`id`, `city`, `CONTENT`, `country`, `created_at`, `email`, `first_name`, `grand_total`, `item_discount`, `last_name`, `status`, `sub_total`, `tax`, `total`, `user_id`) VALUES
('124', 'city', 'test context', 'USA', '2021-05-25 12:40:23.793779', 'test#email.com', 'first name', '100', '10', 'last name', 'active', '20', '10', '200', '192');
CREATE TABLE `order_item` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`discount` decimal(19,2) DEFAULT NULL,
`order_id` int(11) DEFAULT NULL,
`price` decimal(19,2) DEFAULT NULL,
`product_id` int(11) DEFAULT NULL,
`quantity` int(11) DEFAULT NULL,
`sku` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
SQLFiddle: http://sqlfiddle.com/#!9/1d6ba6/1
I use this SQL query with 2 JOINS to get the subsriptions:
SELECT *
FROM subscription
INNER JOIN Orders ON subscription.order_id = Orders.id AND subscription.id = 122
INNER JOIN users ON users.id = users.id AND Orders.user_id = 192
ORDER BY subscription.id;
As you can see I use 2 params in order to make 2 JOINS. Is it possible just to send the user id as a param and based from the match Orders.id AND subscription.id to get the subscription records that are found?
Your query didn't make sense, with ON Clause that links orders and user
So you can achieve the same result, without the user
SELECT *
FROM subscription
INNER JOIN Orders ON subscription.order_id = Orders.id AND subscription.id = 122
INNER JOIN users ON users.id = Orders.user_id
ORDER BY subscription.id;
btw the user of aliases can help keep more overview
SELECT *
FROM subscription s
INNER JOIN Orders o ON s.order_id = o.id AND s.id = 122
INNER JOIN users u ON u.id = o.user_id
ORDER BY s.id;

MySQL - Why query does not sum same type of data if I use more left join?

My schema and sample data set:
CREATE TABLE `bsbi_hedge_fund` (
`id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`fund_name` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`abn_number` varchar(13) COLLATE utf8_unicode_ci DEFAULT NULL,
`parent_company_id` int(11) DEFAULT NULL,
`email` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
`contact_no` varchar(16) COLLATE utf8_unicode_ci DEFAULT NULL,
`address_one` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`address_two` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`city_name` varchar(60) COLLATE utf8_unicode_ci DEFAULT NULL,
`state_name` varchar(60) COLLATE utf8_unicode_ci DEFAULT NULL,
`zip_code` varchar(10) COLLATE utf8_unicode_ci DEFAULT NULL,
`country_tbl_id` int(11) DEFAULT NULL,
`status` varchar(10) COLLATE utf8_unicode_ci DEFAULT 'active',
`created_by` int(11) DEFAULT NULL,
`created_date` datetime DEFAULT NULL,
`modified_by` int(11) DEFAULT NULL,
`modified_date` datetime DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
--
-- Dumping data for table `bsbi_hedge_fund`
--
INSERT INTO `bsbi_hedge_fund` (`id`, `fund_name`, `abn_number`, `parent_company_id`, `email`, `contact_no`, `address_one`, `address_two`, `city_name`, `state_name`, `zip_code`, `country_tbl_id`, `status`, `created_by`, `created_date`, `modified_by`, `modified_date`) VALUES
(1, 'iCAP Hedge Funds', '53616271062', 1, 'icaptrading#gmail.com', '0425175887', '68 Roy Marika Street', '', 'Bonner', 'ACT', '2914', 12, 'active', 1, '2020-02-20 07:02:51', NULL, NULL);
CREATE TABLE `bsbi_company` (
`id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`company_name` varchar(60) COLLATE utf8_unicode_ci DEFAULT NULL,
`abn_number` varchar(13) COLLATE utf8_unicode_ci DEFAULT NULL,
`acn_number` varchar(13) COLLATE utf8_unicode_ci DEFAULT NULL,
`email` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
`contact_no` varchar(16) COLLATE utf8_unicode_ci DEFAULT NULL,
`address_one` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`address_two` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`city_name` varchar(60) COLLATE utf8_unicode_ci DEFAULT NULL,
`state_name` varchar(60) COLLATE utf8_unicode_ci DEFAULT NULL,
`zip_code` varchar(10) COLLATE utf8_unicode_ci DEFAULT NULL,
`country_tbl_id` int(11) DEFAULT NULL,
`status` varchar(10) COLLATE utf8_unicode_ci DEFAULT 'active',
`created_by` int(11) DEFAULT NULL,
`created_date` datetime DEFAULT NULL,
`modified_by` int(11) DEFAULT NULL,
`modified_date` datetime DEFAULT NULL,
`allocated_money` float(17,5) DEFAULT '0.00000',
`hedge_fund_allocation` float(17,5) NOT NULL,
`investment_class_allocation` float(17,5) NOT NULL,
`hedge_fund_money` float(10,3) DEFAULT '0.000',
`inv_class_money` float(10,3) DEFAULT '0.000'
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
--
-- Dumping data for table `bsbi_company`
--
INSERT INTO `bsbi_company` (`id`, `company_name`, `abn_number`, `acn_number`, `email`, `contact_no`, `address_one`, `address_two`, `city_name`, `state_name`, `zip_code`, `country_tbl_id`, `status`, `created_by`, `created_date`, `modified_by`, `modified_date`, `allocated_money`, `hedge_fund_allocation`, `investment_class_allocation`, `hedge_fund_money`, `inv_class_money`) VALUES
(1, 'Investment and Capital Growth for Australian Professional ( ', '53616271062', '2123', 'abc#gmail.com', '2343', '68 Roy Marika Street', '', 'Bonner', 'ACT', '2914', 12, 'active', 1, '2020-02-20 07:01:26', 1, '2020-03-07 12:13:53', 22847.00000, 0.00000, 0.00000, 20000.000, 19000.000);
CREATE TABLE `bsbi_hedge_fund_journal` (
`id` int(11) NOT NULL,
`company_id` int(11) DEFAULT NULL,
`hedge_fund_id` int(11) DEFAULT NULL,
`amount` float(10,3) DEFAULT NULL,
`tran_type` varchar(7) COLLATE utf8_unicode_ci DEFAULT NULL,
`created_by` int(11) DEFAULT NULL,
`created_date` datetime DEFAULT NULL,
`modified_by` int(11) DEFAULT NULL,
`modified_date` datetime DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
--
-- Dumping data for table `bsbi_hedge_fund_journal`
--
INSERT INTO `bsbi_hedge_fund_journal` (`id`, `company_id`, `hedge_fund_id`, `amount`, `tran_type`, `created_by`, `created_date`, `modified_by`, `modified_date`) VALUES
(1, 1, 1, 20000.000, 'credit', 1, '2020-03-07 11:45:40', NULL, NULL);
CREATE TABLE `bsbi_investment_allocation_class_journal` (
`id` int(11) NOT NULL,
`hedge_fund_id` int(11) DEFAULT NULL,
`investment_class_id` int(11) DEFAULT NULL,
`amount` float(10,3) DEFAULT NULL,
`tran_type` varchar(7) COLLATE utf8_unicode_ci DEFAULT NULL,
`created_by` int(11) DEFAULT NULL,
`created_date` datetime DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
--
-- Dumping data for table `bsbi_investment_allocation_class_journal`
--
INSERT INTO `bsbi_investment_allocation_class_journal` (`id`, `hedge_fund_id`, `investment_class_id`, `amount`, `tran_type`, `created_by`, `created_date`) VALUES
(1, 1, 1, 18000.000, 'credit', 1, '2020-03-07 11:46:09'),
(2, 1, 1, 2000.000, 'credit', 1, '2020-03-07 12:12:02'),
(3, 1, 1, 1000.000, 'debit', 1, '2020-03-07 12:13:53');
...and fiddle of same ( http://sqlfiddle.com/#!9/9cd46d/2 ):
I have written the following query to fetch some data from the database:
SELECT
hf.*, com.company_name company_name, com.id com_id,
IFNULL( SUM( hfc.amount ), 0 ) hedge_credit, IFNULL( SUM( hfd.amount ), 0 ) hedge_debit,
IFNULL( SUM( cjc.amount ), 0 ) class_credit, IFNULL( SUM( cjd.amount ), 0 ) class_debit
FROM bsbi_hedge_fund hf
INNER JOIN bsbi_company com ON hf.parent_company_id = com.id
LEFT JOIN bsbi_hedge_fund_journal hfc ON (hfc.hedge_fund_id = hf.id AND hfc.tran_type='credit')
LEFT JOIN bsbi_hedge_fund_journal hfd ON ( hfd.hedge_fund_id = hf.id AND hfd.tran_type = 'debit' )
LEFT JOIN bsbi_investment_allocation_class_journal cjc ON (cjc.hedge_fund_id = hf.id AND cjc.tran_type = 'credit' )
LEFT JOIN bsbi_investment_allocation_class_journal cjd ON (cjd.hedge_fund_id = hf.id AND cjd.tran_type = 'debit' )
ORDER BY hf.id ASC
Here is the output of this query:
The problem I face is: hedge_credit value is 20000 but it shows 40000! similarly class_debit is 1000 but it shows 2000
After doing some R&D what I found is: bsbi_investment_allocation_class_journal table has two entry having tran_type = credit but for some unknown reason the following line of my query fetch two rows, rather sum the values (and I fear the same thing will happen to other left join if they also have more than one record of the same type!)
LEFT JOIN bsbi_investment_allocation_class_journal cjc ON (cjc.hedge_fund_id = hf.id AND cjc.tran_type = 'credit' )
If I add Group By clause to above query then I got:
Notice that class_credit has two different values that should sum up but does not sum for an unknown reason!!
Can anyone tell me what is actually wrong in my query that raises this issue?
- Thanks
Joins generate all possible combinations of rows that meet join criteria. Because you're using only hfc.hedge_fund_id = hf.id to join tables, you are duplicating rows. If there were three transactions in total, each would be tripled..
You'll need to select more data from the tables containing transactions to keep the rows unique: timestamps or transaction ids. I would usually select the unique rows that I want first, then left join the non-unique data (name, country, etc) to each row.
I got the solution from this: https://dba.stackexchange.com/questions/154586/sum-over-distinct-rows-with-multiple-joins
If someone faces the exact type of problem then they can check this solution: https://dba.stackexchange.com/questions/154586/sum-over-distinct-rows-with-multiple-joins

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

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

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.

Need help to correct MySQL query results from two tables

I have two tables one is events and one is periods. I want to select these two tables data in a single query. These two tables have a common field start_time and i want the results to be ordered by that column.
Table structure of the tables:
CREATE TABLE IF NOT EXISTS `events` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`event_name` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
`start_time` time NOT NULL,
`end_time` time NOT NULL,
`is_repeated` tinyint(4) NOT NULL DEFAULT '0',
`alarm_type` enum('set_date','days','monthly') COLLATE utf8_unicode_ci NOT NULL,
`event_alarm_date` date DEFAULT NULL,
`alarm_days` set('Sat','Sun','Mon','Tue','Wed','Thu','Fri') COLLATE utf8_unicode_ci DEFAULT NULL,
`monthly_alarm_days` set('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') COLLATE utf8_unicode_ci DEFAULT NULL,
`alarm_audio` varchar(30) COLLATE utf8_unicode_ci NOT NULL,
`created_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`count_down_time` tinyint(4) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=7 ;
--
-- Dumping data for table `events`
--
INSERT INTO `events` (`id`, `event_name`, `start_time`, `end_time`, `is_repeated`, `alarm_type`, `event_alarm_date`, `alarm_days`, `monthly_alarm_days`, `alarm_audio`, `created_on`, `count_down_time`) VALUES
(1, 'Lunch Break', '10:30:45', '11:30:45', 1, 'days', NULL, 'Mon,Wed', NULL, '1411587500.mp3', '0000-00-00 00:00:00', 0),
(2, 'Openning Ceremony', '10:30:45', '11:30:45', 1, 'monthly', NULL, NULL, '2,3,4', '1411587568.mp3', '0000-00-00 00:00:00', 0),
(3, 'Inspection', '10:30:45', '12:45:30', 0, 'set_date', '2014-09-26', NULL, NULL, '1411587695.mp3', '0000-00-00 00:00:00', 0),
(5, 'Test2', '10:30:45', '11:30:45', 1, 'monthly', NULL, NULL, '3,4,5', '1411595801.mp3', '2014-09-24 21:56:41', 0),
(6, 'Test3', '22:20:30', '23:25:30', 1, 'days', NULL, 'Sun,Mon', NULL, '1411597086.mp3', '2014-09-24 22:18:06', 0);
CREATE TABLE IF NOT EXISTS `periods` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`period_name` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
`start_time` time NOT NULL,
`repeat_on` set('Sat','Sun','Mon','Tue','Wed','Thu','Fri') COLLATE utf8_unicode_ci DEFAULT NULL,
`count_down_time` tinyint(4) NOT NULL DEFAULT '40',
`created_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`period_audio` varchar(30) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=3 ;
--
-- Dumping data for table `periods`
--
INSERT INTO `periods` (`id`, `period_name`, `start_time`, `repeat_on`, `count_down_time`, `created_on`, `period_audio`) VALUES
(1, 'Quran Recitation', '08:15:00', 'Mon,Wed', 30, '2014-09-25 01:30:26', ''),
(2, 'Morning Assembly', '08:15:00', 'Sun,Mon,Wed', 30, '2014-09-28 04:25:24', '');
I have written query below. This query gets 8 records while according to the tables data it should get 5 records.
SELECT pr.period_name,
pr.start_time as period_start_time,
pr.repeat_on, pr.created_on as period_created_on,
pr.count_down_time as period_count_down_time,
pr.period_audio, ev.event_name,
ev.start_time as event_start_time,
ev.end_time as event_end_time,
ev.is_repeated, ev.alarm_type,
ev.event_alarm_date,ev.alarm_days,
ev.monthly_alarm_days,
ev.alarm_audio,
ev.created_on as event_created_on,
ev.count_down_time as event_count_down_time
FROM periods as pr, events as ev
WHERE
FIND_IN_SET('Mon',repeat_on)>0 AND
CASE alarm_type WHEN 'set_date' THEN FIND_IN_SET('2014-09-25',event_alarm_date)>0
WHEN 'days' THEN FIND_IN_SET('Mon',alarm_days) > 0
WHEN 'monthly' THEN FIND_IN_SET('2',monthly_alarm_days) > 0
END = 1
ORDER BY pr.start_time AND ev.start_time
Any help appreciated.