2012-12-27 18 views
0

我有一个小应用程序(PHP/MySQL)来管理公寓。有一个condos表,apartments表,owners表和account表。sql查询找到三个或更多月债务的用户

account表中,我有字段month_paidyear_paid(等等)。

每次有人支付月费,表格会更新月份和年份的数字。

下面是一些样本表结构:

condos表:

+----+------------+---------+ 
| id | condo_name | address | 
+----+------------+---------+ 

apartments表:

+----+----------------+----------+ 
| id | apartment_name | condo_id | 
+----+----------------+----------+ 

owners表:

+----+--------------+------------+ 
| id | apartment_id | owner_name | 
+----+--------------+------------+ 

account表:

+----+----------+----------+------------+-----------+ 
| id | owner_id | condo_id | month_paid | year_paid | 
+----+----------+----------+------------+-----------+ 

所以,如果我有这样的帐户表中的记录,这意味着该老板支付2012年8月:

+----+----------+----------+------------+-----------+ 
| id | owner_id | condo_id | month_paid | year_paid | 
+----+----------+----------+------------+-----------+ 
| 1 |  1 |  1 |   8 |  2012 | 
+----+----------+----------+------------+-----------+ 

我想知道的是如何使SQL查询(使用PHP)使拥有三个或三个月以上债务的所有者,换句话说,在过去三个月或更长时间内没有支付费用的所有者。

如果可能的话,该数据应该由公寓进行分组,这样的:

CONDO XPTO: 
Owner 1: 3 months debt 
Onwer 2: 5 months debt 

CONDO BETA 
Owner 1: 4 months debt 
Onwer 2: 6 months debt 

感谢

+2

请问您可以添加样品记录与期望的结果与你的问题? –

回答

0

修复您的帐户表。 DROP COLUMN是可选的,如果他们有依赖关系,你可能想保留它们。

ALTER TABLE account ADD COLUMN date_paid DATETIME; 
UPDATE account SET date_paid = CONCAT(year_paid,'-',month_paid,'-01'); 
--ALTER TABLE account DROP COLUMN year_paid; 
--ALTER TABLE account DROP COLUMN month_paid; 

这就是你如何得到你的数据。我使用了LEFT OUTER JOIN s以防万一您有任何遗失的所有者或公寓记录。

SELECT c.condo_name, 
o.owner_name, 
min(PERIOD_DIFF(DATE_FORMAT(now(), '%Y%m'), DATE_FORMAT(date_paid, '%Y%m'))) min_months_debt 
FROM account a 
LEFT OUTER JOIN condos c ON (c.id = a.condo_id) 
LEFT OUTER JOIN owners o ON (a.owner_id = o.id) 
WHERE a.date_paid <= DATE_ADD(NOW(), INTERVAL -3 MONTH) 
GROUP BY c.condo_name, o.owner_name 
ORDER BY c.condo_name 

P.S.以上仅适用于至少进行一次付款的公寓业主。如果您想查看从未付款的公寓所有者,则必须将公寓与帐户表之外的所有者相关联。或者,当您将公寓与业主关联时,您可能会创建一个帐户记录,在这种情况下,您没有问题。

+0

这似乎是这样,但我得到太多的结果。我想这是因为账单表已经支付了所有的月份。如果业主支付1月行军,则表中会有3排。这样我得到6个结果为这个所有者。也许选择不同? – fana

+0

我认为GROUP BY可能会更好,但是您需要决定是否在months_debt字段上执行max()或min()。 – paulgrav

4

你需要编写一个查询是这样的:

SELECT 
    * 
FROM 
    owners 
JOIN 
    account 
ON 
    owners.id = account.owners_id 
WHERE 
    CONCAT(account.year_paid , '-' , account.month_paid , '-01') <= DATE_ADD(NOW(), INTERVAL -3 MONTH); 

可悲的是这是关于我可以向你提供你提供的信息。如果你可以显示更详细的表格结构,我可以帮助你更多。

1

通过以这种方式存储它,可以让自己变得更加困难。现在你需要自己计算月的差异。你不能只检查几个月,因为例如在1月份你还需要考虑这一年。

SELECT * 
FROM owners 
JOIN account ON owners.Id=account.ownersId 
WHERE ( 
    account.year_paid = year(now) 
    AND (
    month(now)-account.month_paid>=3 
) 
) OR (
    account.year_paid = year(now)-1 
    AND (
    month(now)>=3 
    OR (
     account.month_paid - month(now) <= 10 
     AND month(now) = 1 
    ) 
    OR (
     account.month_paid - month(now) <= 11 
     AND month(now) = 2 
    ) 
) 
) OR (
    account.year_paid < year(now)-1 
) 

最好只存储lastpaid时间在datetime collumn所以你可以使用最新的功能。

+0

是的,你是完全正确的,但我从另一家公司继承此代码... – fana

+1

尽管其他答案复杂得多,但此查询可能运行得最快。 @hugo-delsing避免了写一个在所有记录上执行函数的where子句。 – paulgrav

0

如果我理解正确,你有两个不同的飞蛾和年份领域。为什么? 如果你有一个字段说paid_date此查询会为你工作

SELECT owner_id from account WHERE NOW()>DATE_ADD(paid_date, INTERVAL 3 MONTH)

如果你可以改变fielfd然后抱歉。我希望这是有帮助的。

UPD: 那么我建议你在查询两个字段(yearmonth)的串联,使它看起来像真正的日期YYYY-MM-DD格式和DATE_ADD功能用它来代替paid_date

+0

这将是伟大的,但正如我所说我继承了代码和数据库。也许我会尝试批量更改表格并添加日期时间字段,并根据月份和年份自动填充它... – fana

+0

@fana查看更新的文章 –

+0

您希望避免在所有记录上执行功能的where子句。例如:'WHERE CONCAT(account.year_paid,' - ',account.month_paid,'-01')<= DATE_ADD(NOW(),INTERVAL -3 MONTH)'。 where子句要求mysql在帐户表中的每个记录上执行一个'CONCAT()'!您也不想这样做:'WHERE NOW()> DATE_ADD(paid_date,INTERVAL 3 MONTH)'因为它在每个帐户记录上执行DATA_ADD()'。索引不会帮助你。你真的想能够写出如下这样的where子句:'WHERE date_paid <= DATE_ADD(NOW(),INTERVAL -3 MONTH)''。 – paulgrav

0

试试这个,

select o.owner_name,c.condo_name from owners o join account a join condos c 
on o.id=a.owner_id and c.id =a.condo_id where year(curdate())=a.year_paid 
and a.month_paid<month(curdate())-3 
0

我还没有看到任何答案,实际上产生你在找什么。以下通过计算当前月份减去最近付款日期来计算债务月份。然后,它串接成果转化的字符串:

select c.condo_name, o.owner_name, 
     cast(YEAR(now)*12+MONTH(now)) - MAX(year_paid*12+month_paid) as varchar(255)), ' month(s) debt' 
from account a join 
    owners o 
    on o.id = a.owner_id join 
    condos c 
    on c.id = a.condo_id 
group by c.condo_name,, o.owner_name 
order by 1, 2 

如果你只想要拖欠纳税人,然后添加一个where子句的效果:

where YEAR(now)*12+MONTH(now)) - MAX(year_paid*12+month_paid) > 1 

因为你没有的一天付款月份,您可能会错过一些临界条件。

+0

你的代码是有道理的,但我不能让它工作。 where子句给我一个“组函数的无效使用” – fana