I want to create a query to calculate the due amount, on a situation where partial payments can be done for specific paymentSchedule id
I have a table with a payment schedule as this:
CREATE TABLE IF NOT EXISTS paymentSchedule (
id int(11) NOT NULL AUTO_INCREMENT,
concept varchar(32) COLLATE utf8_spanish_ci NOT NULL,
student_id int(11) NOT NULL,
dueDate date NOT NULL,
amount decimal(10,2) NOT NULL,
PRIMARY KEY (id)
)
And I have a payments transaction table like this, wherepaymentSchedule_id refers to the above table:
CREATE TABLE IF NOT EXISTS ledger (
id int(11) NOT NULL AUTO_INCREMENT,
paymentDate date NOT NULL,
amount decimal(10,2) NOT NULL,
paymentSchedule_id int(11) NOT NULL,
PRIMARY KEY (id)
)
I tried to to a substraction like here:
How to substract from the resut of two selects in mysql
but that only works if there are fields with the correspondinf paymentSchedule id in the ledger.
What is the right way to do it?
on the other hand, is that the right way to store payment schedules and transactions?
It seems like you are trying to do this?
for each id in paymentSchedule table:
store paymentSchedule.amount - sum( ledger.amount )
In which case you could do:
SELECT paymentSchedule.id,
paymentSchedule.amount - IFNULL(SUM(ledger.amount),0) AS remaining
FROM paymentSchedule
LEFT JOIN ledger ON paymentSchedule.id=ledger.paymentSchedule_id
GROUP BY ledger.paymentSchedule_id
This shows all amounts remaining, regardless of whether a person has paid any of it off or not (thanks to the IFNULL( xxx, 0 )).
Related
I have two customer table, internal and external both with nameļ¼ email address
I have another shopping list table which join these customer table by name.
how I can get the shopping list given name in one sql?
shopping item | customer name| customer email|
is there a way to join one table if not found then join another table?
DDL is like
CREATE TABLE `shoppinglist` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`customername` varchar(40) NOT NULL,
`itemname` varchar(40) NOT NULL,
)
CREATE TABLE `internalcustomer` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(40) NOT NULL,
`email` varchar(40) NOT NULL,
)
CREATE TABLE `externalcustomer` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(40) NOT NULL,
`email` varchar(40) NOT NULL,
)
Currently I have to use two sql
select list.itemname, intcustomer.name, intcustomer.email from shoppinglist list
join internalcustomer intcustomer on intcustomer.name = list.customname;
select list.itemname, extcutomer.name, extcutomer.email from shoppinglist list
join externalcustomer extcutomer on extcutomer.name = list.customname;
ps: the name should be uniq across both table
You may use UNION
select list.itemname, intcustomer.name, intcustomer.email from shoppinglist list
join internalcustomer intcustomer on intcustomer.name = list.customname
UNION
select list.itemname, extcutomer.name, extcutomer.email from shoppinglist list
join externalcustomer extcutomer on extcutomer.name = list.customname;
Please use UNION ALL if you want to allow duplicate values. Else, UNION operator selectes only distinct values
I have two tables that i need to join them
first table i created using this sql query
CREATE TABLE `users` (
`id` bigint PRIMARY KEY AUTO_INCREMENT,
`user_login` varchar(60),
`user_pass` varchar(255),
`first_name` varchar(30),
`last_name` varchar(30),
`user_status` int(2),
`user_phone_number` varchar(20),
`user_email` varchar(100),
`user_billing_info` text,
`user_temp_units` int(2),
`user_flow_units` int(2),
`user_notes` text
);
second table
CREATE TABLE `station_meta` (
`uid` VARCHAR(25) PRIMARY KEY,
`nickname` varchar(30),
`install_date` date,
`latatude` numeric(10,6),
`longitude` numeric(10,6),
`firmware_ver` varchar(10),
`weir_type` int(2),
`weir_width` numeric,
`dist_to_ground` numeric,
`dist_to_weir` numeric,
`service_fee` numeric,
`notes` text
);
i got double rows when i use this sql query
SELECT * FROM station_meta JOIN users
note: uid is something like 9C9Z454Z5CA in case it need to mention it
so there's not any column that is the same in the other table
UPDATE
Data sample
My results
I'm using it in php function in foreach, so i got double results
Appreciate any help
seems you miss a relation between the two tables ..
if you want avoid cartesian product and retrieve just a matching value between the two table you should add a relation as
table user_station_meta (
`id` bigint PRIMARY KEY AUTO_INCREMENT,
user_id bigint
station_meta_uid VARCHAR(25)
)
once you have inserted the matching values
uid, id
9c2748.. 1
BC8CD4.. 5
you can select single matching result as
select u.*. s.*
from user_station_meta us
JOIN station_meta s on s.uid = us.uid
JOIN users u on u.id = us.id
I am trying to create a procedure where my transfer table is joined to my account table. In my transfer table, there are two FK columns that reference the account table id column.
account table:
CREATE TABLE account (
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(30) NOT NULL,
number VARCHAR(30) NOT NULL DEFAULT '',
description VARCHAR(255)NOT NULL DEFAULT '',
is_active BIT(1) NOT NULL DEFAULT b'1',
PRIMARY KEY (id),
UNIQUE account_name (name, number)
);
transfer table:
CREATE TABLE transfer (
id INT NOT NULL AUTO_INCREMENT,
date DATE NOT NULL,
from_account INT NULL,
to_account INT NULL,
amount DECIMAL(12, 2) NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (from_account)
REFERENCES account(id),
FOREIGN KEY (to_account)
REFERENCES account(id)
);
get_account procedure:
CREATE PROCEDURE get_account()
SELECT a.*,
(SUM(t.amount) - SUM(f.amount)) AS balance
FROM account a
LEFT JOIN transfer f
ON a.id = f.from_account
LEFT JOIN transfer t
ON a.id = t.to_account
GROUP BY a.id;
I am trying to subtract the total of the from_accout column from the total of the to_account column. I am able to get the sum of just one column but when I try to get both it returns a NULL.
This seems like it should be easy, but I can't figure it out.
I have 3 database table. The one I store sell data like invoice number, due date, issue date. The second table I have the sell record id stored from previous table, there I store the ammount the person have payed (something like the customer payed only a half of the total price). In the third table I store the products and every row has the sell record id for backreference, in this table I have quantity and subtotal (quantity * price).
What I need is select all the record from first table and based on the sell_id I have to summarize how much they payed from the second table, summarize how many products one purchased and how much does it cost.
I need a little guidance to the right solution because I am stuck.
So far I came to this uggly sollution:
SELECT
(SELECT SUM(payment.sellpayment_amount) FROM es_sellpayment payment WHERE sell.sell_id = payment.sell_id) AS payed,
(SELECT SUM(product.sellproduct_quantity) FROM es_sellproduct product WHERE sell.sell_id = product.sell_id) AS quantity,
(SELECT SUM(product.sellproduct_total) FROM es_sellproduct product WHERE sell.sell_id = product.sell_id) AS total
FROM es_sell sell
It works I get the correct result, but I am unsure/unaware how this will impact later on the performance of the website. I tried the classic left join which gave me wrong results. I am also thinking storing permanently these 3 values on the main table; but this would be the lest preferable method because I had to make at lest 2 seperate SQL queries to retrieve the records.
CREATE TABLE `es_sell` (
`sell_id` int(11) NOT NULL,
`sell_invoice` int(11) NOT NULL,
`sell_note` text COLLATE utf8mb4_unicode_ci NOT NULL,
`sell_deliver` datetime NOT NULL,
`sell_issued` datetime NOT NULL,
`sell_due` datetime NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `es_sellproduct` (
`sellproduct_id` int(11) NOT NULL,
`product_id` int(11) NOT NULL,
`sellproduct_quantity` int(11) NOT NULL,
`sellproduct_price` int(11) NOT NULL,
`pricetype_id` int(11) NOT NULL,
`sellproduct_total` decimal(11,3) NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `es_sellpayment` (
`sellpayment_id` int(11) NOT NULL,
`sellpayment_amount` decimal(11,3) NOT NULL,
`sell_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Use sub-queries to aggregate the associated tables to ensure that you're only ever joining one row to one row...
SELECT
sell.sell_id,
payment.payed,
product.quantity,
product.total
FROM
es_sell sell
LEFT JOIN
(
SELECT
sell_id,
SUM(sellpayment_amount) AS payed
FROM
es_sellpayment payment
GROUP BY
sell_id
)
payment
ON payment.sell_id = sell.sell_id
LEFT JOIN
(
SELECT
sell_id,
SUM(sellproduct_quantity) AS quantity,
SUM(sellproduct_total ) AS total
FROM
es_sellproduct
GROUP BY
sell_id
)
product
ON product.sell_id = sell.sell_id
If sell_id isn't unique in the sell table, you can aggregate again in the outer query.
I have redesigned my database structure to use PRIMARY and FOREIGN KEYs to link the entries in my 3 tables together, and I am having problems trying to write queries to select data in one table given data in a another table. Here is an example of my 3 CREATE TABLE statements:
CREATE TABLE IF NOT EXISTS players (
id INT(10) NOT NULL AUTO_INCREMENT,
username VARCHAR(16) NOT NULL,
uuid VARCHAR(200) NOT NULL DEFAULT 0,
joined TIMESTAMP DEFAULT 0,
last_seen TIMESTAMP DEFAULT 0,
PRIMARY KEY (id)
);
/* ^
One |
To
| One
v
*/
CREATE TABLE IF NOT EXISTS accounts (
id INT(10) NOT NULL AUTO_INCREMENT,
account_id INT(10) NOT NULL,
pass_hash VARCHAR(200) NOT NULL,
pass_salt VARCHAR(200) NOT NULL,
created BIGINT DEFAULT 0,
last_log_on BIGINT DEFAULT 0,
PRIMARY KEY (id),
FOREIGN KEY (account_id) REFERENCES players(id) ON DELETE CASCADE
) ENGINE=InnoDB;
/* ^
One |
To
| Many
v
*/
CREATE TABLE IF NOT EXISTS purchases (
id INT(10) NOT NULL AUTO_INCREMENT,
account_id INT(10) NOT NULL,
status VARCHAR(20) NOT NULL,
item INT NOT NULL,
price DOUBLE DEFAULT 0,
description VARCHAR(200) NOT NULL,
buyer_name VARCHAR(200) NOT NULL,
buyer_email VARCHAR(200) NOT NULL,
transaction_id VARCHAR(200) NOT NULL,
payment_type VARCHAR(20) NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (account_id) REFERENCES accounts(account_id) ON DELETE CASCADE
) ENGINE=InnoDB;
Say for example, I want to select all the usernames of users who purchased anything greater than $30. All the usernames are stored in the players table, which is linked to the accounts table and that is linked to the purchases table. Is this this the best way to design this relational database? If so, how would I run queries similar to the above example?
I was able to get get all of a users purchase history given their username, but I did it with 2 sub-queries... Getting that data should be easier than that!
Here is the SELECT query I ran to get all of a players purchase data:
SELECT *
FROM purchases
WHERE account_id = (SELECT id FROM accounts WHERE account_id = (SELECT id FROM players WHERE username = 'username'));
Also, when I try to make references to the other tables using something like 'players.username', I get an error saying that the column doesn't exist...
I appreciate any help! Thanks!
Your design is ok in my opinion. The relation between players and account is one-to-many and not one-to-one since this way, you can have two tuples referencing a single player.
I would write the query you need as:
SELECT DISTINCT p.id, p.username
FROM players p INNER JOIN accounts a ON (p.id = a.account_id)
INNER JOIN purchases pc ON (a.id = pc.account_id)
WHERE (pc.price > 30);
As Sam suggested, I added DISTINCT to avoid repeating id and username in case a user have multiple purchases.
Note the id is here to avoid confusion among repeated usernames.