0

我的工作职能之一是负责在大型新闻通讯订阅数据库上进行挖掘和营销。我的每一份时事通讯都有四列(newsletter_status、newsletter_datejoined、newsletter_dateunsub 和 newsletter_unsubmid)。

除了这些专栏之外,我还有一个我们的客户服务部门的master unsub专栏。可以更新以适应希望从我们所有邮件中删除的愤怒订阅者,如果发生硬退回(或设定数量的软退回),另一个列会更新,称为 emailaddress_status。

当我为一个列表提取当前有效订阅者的计数时,我使用以下语法:

select count (*) from subscriber_db
WHERE (emailaddress_status = 'VALID' OR emailaddress_status IS NULL)
AND newsletter_status = 'Y'
and unsub = 'N' and newsletter_datejoined >= '2013-01-01';

我想要的是一个查询,它查找所有具有 %_status 的列,上述条件按当前计数大小排序。

我希望它看起来像这样:

在此处输入图像描述

等等

我已经在网上搜索了几个月来寻找类似的东西,但是除了在终端中运行它们并导出结果之外,我无法在一个查询中成功地获得它们。

我正在运行 PostgreSQL 9.2.3。

一个合适的测试用例将是每个与我在运行单个查询时得到的计数相匹配的总和。

这是我对序数放置、column_type、char_limit 和 is_nullable的模糊表定义。

4

2 回答 2

3

您的架构绝对令人恐惧:

24  ***_status  text        YES
25  ***_status  text        YES
26  ***_status  text        YES
27  ***_status  text        YES
28  ***_status  text        YES
29  ***_status  text        YES

我认为被屏蔽***的地方类似于出版物/通讯/等的名称。

需要阅读有关数据规范化的信息,否则您将遇到一个不断增长的问题,直到您达到PostgreSQL 的行大小限制

由于每个感兴趣的项目都在不同的列中,因此使用现有模式解决此问题的唯一方法是使用 PL/PgSQL 的EXECUTE format(...) USING .... 您可能认为这只是一个临时选项,但这有点像使用打桩机将方钉塞入圆孔,因为锤子不够大。

SQL 中没有列名通配符,例如*_statusor %_status。列是行的固定组成部分,具有不同的类型和含义。每当您发现自己想要这样的东西时,这表明您的设计需要重新考虑。

我不打算写一个例子,因为(a)这是一家电子邮件营销公司,(b)“混淆”模式对于任何类型的测试都是完全不可用的,如果没有大量的手动工作重写它。(将来,请为您的虚拟数据提供CREATE TABLEINSERT声明,或者更好的是http://sqlfiddle.com/)。format通过快速搜索 Stack Overflow,您将在 PL/PgSQL 中找到许多动态 SQL 的示例 - 以及有关如何通过正确使用来避免由此产生的 SQL 注入风险的警告。我以前写过一堆。

为了您的理智和其他需要在此系统上工作的人的理智,规范化您的模式

您可以在规范化表上创建一个视图以呈现旧结构,让您有时间调整您的应用程序。通过更多的工作,您甚至可以定义DO INSTEAD视图触发器(较新的 Pg 版本)或RULE(较旧的 Pg 版本)以使视图可更新和可插入,因此您的应用程序甚至无法判断任何内容已更改 - 尽管这是为了性能成本,所以如果可能的话,最好调整应用程序。

从这样的事情开始:

CREATE TABLE subscriber (
    id serial primary key,
    email_address text not null,
    -- please read http://www.kalzumeus.com/2010/06/17/falsehoods-programmers-believe-about-names/
    -- for why I merged "fname" and "lname" into one field:
    realname text,
    -- Store birth month/year as a "date" with a "CHECK" constraint forcing it to be the 1st day
    -- of the month. Much easier to work with.
    birthmonth date,
    CONSTRAINT birthmonth_must_be_day_1 CHECK ( extract(day from birthmonth) = 1),
    postcode text,
    -- Congratulations! You made "gender" a "text" field to start with, you avoided
    -- one of the most common mistakes in schema design, the boolean/binary gender
    -- field!
    gender text,
    -- What's MSO? Should have a COMMENT ON...
    mso text,
    source text,
    -- Maintain these with a trigger. If you want modified to update when any child record
    -- changes you can do that with triggers on subscription and reducedfreq_subscription.
    created_on timestamp not null default current_timestamp,
    last_modified timestamp not null,
    -- Use the native PostgreSQL UUID type, after running CREATE EXTENSION "uuid-ossp";
    uuid uuid not null,
    uuid2 uuid not null,
    brand text,

    -- etc etc
);

CREATE TABLE reducedfreq_subscription (
    id serial primary key,
    subscriber_id integer not null references subscriber(id),
    -- Suspect this was just a boolean stored as text in your schema, in which case
    -- delete it.
    reducedfreqsub text,
    reducedfreqpref text,
    -- plural, might be a comma list? Should be in sub-table ("join table")
    -- if so, but without sample data can only guess.
    reducedfreqtopics text,
    -- date can be NOT NULL since the row won't exist unless they joined
    reducedfreq_datejoined date not null,
    reducedfreq_dateunsub date
);

CREATE TABLE subscription (
    id serial primary key,
    subscriber_id integer not null references subscriber(id),
    sub_name text not null,
    status text not null,
    datejoined date not null,
    dateunsub date
);

CREATE TABLE subscriber_activity (
    last_click  timestamptz,
    last_open   timestamptz,
    last_hardbounce timestamptz,
    last_softbounce timestamptz,
    last_successful_mailing timestamptz
);
于 2013-07-09T01:12:05.847 回答
0

仅仅称它为“可怕的”表明你非常机智和善良。谢谢你。:) 我最近才继承了这个模式(最初是由 StrongMail 的人创建的)。

今年我的路线图上有一个完整的关系数据库重建项目——样本规范化与我一直在做的工作非常一致。关于实名的非常有趣的见解,我没有真正考虑过。我想 StrongMail 爆发的唯一原因是名字电子邮件个性化。

MSO 是多系统运营商(有线电视公司)。我们是一家大型生活方式媒体公司,我们制作的时事通讯涉及食品、旅游、家庭和园艺。

我正在为此创建一个小提琴 - 我是新来的,所以我会更加注意你们需要能够提供的帮助。谢谢!

于 2013-07-09T17:46:37.200 回答