Sql query full join - php

I have 2 tables in mariadb which are treatments and payments.
Treatments: id(int(11)), treatment_name(varchar(255)), treatment_date(date)
Payments: id(int(11)), treatment_id(int(11)), payment_amount(decimal(10,2)), payment_date(date)
I want to list records from both table for a given date range, for example from 2016-01-01 to 2016-06-06
1-If the treatment is in between the given date range and has payment OR
2-if the treatment isn't in between the date range BUT has payment with the payment date is in between the given date range.
Anyone can help me for setting the query?

If I understand correctly, you don't need a full outer join. You simply need an inner join along with the correct where clause:
select t.*, p.*
from treatments t inner join
payments p
on t.id = p.treatment_id
where t.treatment_date between '2016-01-01' and '2016-06-06' or
p.payment_date between '2016-01-01' and '2016-06-06';

This can be done using UNION as follows,
SELECT * FROM Treatments WHERE treatment_date BETWEEN #01/01/2016# AND #06/06/2016#
UNION
SELECT * FROM Payments WHERE treatment_date BETWEEN #01/01/2016# AND #06/06/2016#
use this as single Query.

To give you a start, the following will join both tables, you will need to add your filtering based on the date:
SELECT *
FROM Treatments as t1, Payments as t2
WHERE t1.id = t2.treatment_id;
I believe you can do the rest on your own.

Related

MySQL query to generate only negative daily differences

I'm learning mysql and am having difficult time getting my head around more complicated outputs - mainly the logic part... I have a simple database that contains 2 tables with 1 connection - design is here https://prnt.sc/mfmwji
I need to create a report that displays daily balance of only negative states (so only if person is in a negative balance) for the past 6 months.
I've put together query that displays only differences when they're negative, but it does not 'connect' them to rows before them... only displays the withdraws so to say.
I've played around with query but this is the 'best' thing I've came up with... I've tried to wrap the difference with sum function but that just sums the whole thing and doesn't return daily difference.
SELECT
T1.name AS Name,
T2.withdraw - T2.deposit AS Difference,
DATE_FORMAT(T2.date, '%Y-%m-%d') AS Date
FROM
users AS T1
INNER JOIN transactions AS T2
ON
T1.id = T2.user_id
WHERE
(T2.withdraw - T2.deposit) > 0
The query returns this output (its just a part of result since I got 100 results)
http://prntscr.com/mfn0xf
The deposits and withraws for Pearl Champlin so you get the idea are:
http://prntscr.com/mfn15a
I've tried to check other questions on SO but they usually point to other problems and are not specific to my problem.
Thanks in advance for any information you think I should check out!
You could use a subquery to retrieve the balance up to date. Then, in an outer query, you can filter for where that balance is negative:
select *
from (
select u.name,
t.date,
t.deposit - t.withdraw action,
( select sum(deposit - withdraw)
from transactions
where user_id = u.id
and date <= t.date ) as balance
from users as u
inner join transactions as t
on u.id = t.user_id
) balances
where balance < 0
order by 1, 2
This is what you asked. It shows the report for one user. I don't know if there is a way to make this for all the user at the same time. Maybe it can help you to find what you want.
SELECT
PreAgg.name,
(PreAgg.withdraw - PreAgg.deposit) AS Difference,
#PrevBal := #PrevBal + (PreAgg.withdraw - PreAgg.deposit) AS Balance
FROM
(SELECT
T1.name,
T2.deposit,
T2.withdraw,
(T2.withdraw - T2.deposit) AS Difference,
T1.id
FROM
users AS T1
INNER JOIN transactions AS T2
ON
T1.id = T2.user_id
ORDER BY
T2.id ) AS PreAgg,
(SELECT #PrevBal := 0) as InitialVar
WHERE PreAgg.id = 1

MySQL query exclude entry depending on date

I need help with a MySQL query. I have 2 tables, clients and payments. The table clients has 2 fields id and name. The table payments has id, id_clients, pay_month. The clients need to pay every month a certain amount.
I want to search only the name of clients which has not paid the current month.
my query
SELECT name FROM clients WHERE id NOT IN (SELECT DISTINCT id_client FROM payments WHERE pay_month > '2014-03-15' ORDER BY pay_month DESC)
I managed to resolve my query.
I used php to store the date $today = date("Y-m-d");
SELECT DISTINCT clients.id, clients.name FROM clients WHERE clients.id NOT IN (SELECT DISTINCT id_clients FROM payments WHERE pay_month > '".$today."' ORDER BY pay_month DESC) ORDER BY clients.name ASC
Thank you everyone for your help.
Maybe something like this.
SELECT
c.name as client_name,
p.pay_month as payment_month
FROM clients c
LEFT JOIN payments p on p.id_clients = c.id
WHERE p.id IS NULL AND YEAR(p.pay_month) >= YEAR(NOW()) AND MONTH(p.pay_month) > MONTH(NOW());
if you could give us some sample data i can build a sql fiddle and do it much easier.
just edited to fix the date format/check

How to Join mysql Tables With Sum

How can i join the following SQL query?
SELECT SUM( payments.amount ) , SUM( payments.balance ) , records.recordID, records.record
FROM fees AS payments
INNER JOIN recordtype AS records ON payments.referenceID = records.recordID
the above query is giving the following error
MySQL said: Documentation
1140 - Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause
My Expectation results would like each recordID to show balance and amount it has.
Thank and Regards, all Suggestions & Questions are welcome
SELECT SUM( payments.amount ) , SUM( payments.balance ) , records.recordID, records.record
FROM fees AS payments INNER JOIN recordtype AS records
ON payments.referenceID = records.recordID
GROUP BY records.recordID, records.record
When you have used an aggregate function in your SELECT statement you have to tell sql how to do the aggregates on that column by using GROUP BY clause,
Simple rule of thumb, When you have used an aggregate function (COUNT,MAX, MIN, SUM, AVG) in a SELECT statement any other columns that are in that SELECT and are not contained in any aggregate function MUST come in GROUP BY clause of that statement.
Your SQL statemant won't work because you have not made it clear what to count. If you use sum() or max() or min() or something like that, you have to use a group by in your statement. So, e.g. if you want to calculate the sum of the amount your customers purchase in your shop use something like this:
SELECT SUM( payments.amount )
FROM payments
inner join customer on payments.customer_id = customer.id
GROUP BY customer.id
And, if you wan't to check only one customer you have to use the SQL clouse "haveing". Where won't work in that case.

How to select from one table where difference with (sum) from another table?

I have two tables with following fields:
...
orders.orderID
orders.orderValue
and
payments.orderID
payments.payVal
In payments.payVal there will be incremental payments for each order (many-to-one).
What I need it so select ALL orders from orders where there is payment left (orders.orderValue - ((sum)payments.payVal) > 0 ).
The only thing I can come up to right now is a (foreach) using the orderID, but I cannot do that for some particular reasons. I also cannot add a column inside table to hold the value for some reasons too.
What I need, is to perform the entire selection in one single SQL Query something that resembles this idea: SELECT * FROM orders WHERE <... each(orderValue - (sum(payVal))) > 0 ...>
SELECT *, SUM(p.payVal) AS TotalPayed
FROM orders o
LEFT JOIN payments p ON o.orderID = p.orderID
GROUP BY o.orderID
HAVING SUM(p.payVal) < o.orderValue
This should provide you with the necessary fields, although I would advise you to select specific fields with this query.
The LEFT JOIN makes sure you get every order, even if there are no payments made yet.
SQL Fiddle
Looks like we came to the same solution,
http://sqlfiddle.com/#!2/9a657/18
SELECT * FROM `orders`
LEFT JOIN `payments` AS p ON `orders`.`orderID` = p.`orderID`
GROUP BY `orders`.`orderID`
HAVING SUM(p.`payVal`) <= 0

Retrieving row count and returning 0 when no rows

I've written a query to retrieve how many website signups I've had every day:
SELECT created, COUNT(id)
FROM signups
GROUP BY created
ORDER BY created desc
However, this only retrieves rows for days where people have actually signed up. If nobody has signed up in a day, I would like to return 0 for that day. Is there a way to do this using SQL or will I have to parse through the results using PHP?
Assuming created to be of type date for lack of information.
Postgres provides the wonderful generate_series() to make this easy:
SELECT d.created, COUNT(s.id) AS ct
FROM (
SELECT generate_series(min(created)
, max(created), interval '1 day')::date AS created
FROM signups
) d
LEFT JOIN signups s USING (created)
GROUP BY 1
ORDER BY 1 DESC;
This retrieves minimum and maximum day from your table automatically and provides one row per day in between.
You can use NULLIF function:
SELECT created, NULLIF(COUNT(id), 0)
FROM signups
GROUP BY created
ORDER BY created desc
Documentation: http://www.postgresql.org/docs/8.1/static/functions-conditional.html
You need to make use of a calendar table that has a series of dates and join with it
select cal.created,coalesce(total) as total from calender_table as cal left join
(
SELECT created, COUNT(id) as total
FROM signups
GROUP BY created
) as source on cal.created=source.created
ORDER BY cal.created desc
You should create a calendar table in your database (or generate it in a query) and join it with yours then you will get 0 for empty days
SELECT calendar.c_date, COUNT(signups.id)
FROM calendar
left join signups on calendar.c_date=signups.created
GROUP BY c_date
ORDER BY c_date desc
Here is a way to make a calendar date in PostgreSQL

Categories