ORM 获取连接表的行数

Posted

技术标签:

【中文标题】ORM 获取连接表的行数【英文标题】:ORM get joined table row count 【发布时间】:2015-12-14 21:00:59 【问题描述】:

我目前在一个项目中使用 Witty 和 DBO 以及 SQLite3,现在我需要加入一个相关表来获取行数。

表格

CREATE TABLE "rfnode" (
  "mac" varchar(16) not null,
  "zone" integer not null,
  "subZone" integer not null,
  "unit" text not null,
  "pwm" integer not null,
  "led" integer not null,
  "network" integer not null,
  "lastContact" text,
  "ioConfiguration" integer not null,
  primary key ("mac")
)

CREATE TABLE "nodemeasure" (
  "id" integer primary key autoincrement,
  "mac" text not null,
  "type" integer not null,
  "date" text,
  "batchDate" text,
  "value" real not null
)

典型的 SQL 查询是:

SELECT
    rn.*,
    COUNT(nm.id) AS measuresCount
FROM rfnode rn
LEFT JOIN nodemeasure nm
    ON nm.mac = rn.mac
GROUP BY rn.mac

现在的问题是我不知道如何使用 Wt/DBO 库来查询和获取结果。

第一次尝试

class RFNode

    public:
        std::string mac, unit;
        int zone = 0, subZone = 0, pwm = 0, led = 0, network = 0, ioConfiguration = 0, measuresCount = 0;
        Wt::WDateTime lastContact;

        RFNode()
        
            mac             = "";
            zone            = 0;
            subZone         = 0;
            unit            = "";
            pwm             = 8;
            led             = 8;
            network         = 0;
            ioConfiguration = 0;
            measuresCount   = 0;
        

        RFNode(std::string p_sMAC, int p_nZone, int p_nSubZone, std::string p_sUnit, int p_nPWM, int p_nLED, int p_nNetwork, Wt::WDateTime p_oLastContact, int p_nIOConfiguration, int p_nMeasuresCount = 0)
        
            mac             = p_sMAC;
            zone            = p_nZone;
            subZone         = p_nSubZone;
            unit            = p_sUnit;
            pwm             = p_nPWM;
            led             = p_nLED;
            network         = p_nNetwork;
            lastContact     = p_oLastContact;
            ioConfiguration = p_nIOConfiguration;
            measuresCount   = p_nMeasuresCount;
        

        template<class Action>
        void persist(Action& a)
        
            dbo::id(a,      mac,            "mac",16);
            dbo::field(a,   zone,           "zone");
            dbo::field(a,   subZone,        "subZone");
            dbo::field(a,   unit,           "unit");
            dbo::field(a,   pwm,            "pwm");
            dbo::field(a,   led,            "led");
            dbo::field(a,   network,        "network");
            dbo::field(a,   lastContact,    "lastContact");
            dbo::field(a,   ioConfiguration,"ioConfiguration");
            dbo::field(a,   measuresCount,  "measuresCount");
        ;
;

使用查询:

Wt::Dbo::collection<Wt::Dbo::ptr<RFNode>> lTemp = m_oSession.query<Wt::Dbo::ptr<RFNode>>("SELECT rn.*, COUNT(nm.id) AS measuresCount FROM rfnode rn LEFT JOIN nodemeasure nm ON nm.mac = rn.mac").resultList();

是指向Session::query(): too many aliases for result

第二次尝试

使用相同的类 RFNode,除了字段 measuresCount 被删除。

typedef Wt::Dbo::ptr_tuple<RFNode, int>::type RFNodeJoin;
        typedef Wt::Dbo::collection<RFNodeJoin> RFNodeJoinC;

        RFNodeJoinC lTemp = m_oSession.query<RFNodeJoin>("SELECT rn.*, COUNT(nm.id) AS measuresCount FROM rfnode rn LEFT JOIN nodemeasure nm ON nm.mac = rn.mac GROUP BY rn.mac").resultList();

        std::vector<RFNodeJoin> lTransition(lTemp.begin(),lTemp.end());

但它没有编译,导致错误:error: request for member ‘persist’ in ‘obj’, which is of non-class type ‘int’。我想我需要为每个表映射一个类,但由于我想要一个计数并且没有现有字段,我认为 int 类无法完成这项工作。

【问题讨论】:

【参考方案1】:

终于通过反复试验,我找到了解决方案...

首先,RFNode 类不再具有 measuresCount 字段。

请求和迭代如下:

Wt::Dbo::collection<boost::tuple<Wt::Dbo::ptr<RFNode>, int>> lTemp = m_oSession.query<boost::tuple<Wt::Dbo::ptr<RFNode>, int>>("SELECT rn, COUNT(nm.id) FROM rfnode rn LEFT JOIN nodemeasure nm ON nm.mac = rn.mac GROUP BY rn.mac").resultList();

for(Wt::Dbo::collection<boost::tuple<Wt::Dbo::ptr<RFNode>, int>>::const_iterator i = lTemp.begin();i != lTemp.end();++i)

    Wt::Dbo::ptr<RFNode> pRFNode;
    int nNodeMeasureCount;

    boost::tie(pRFNode,nNodeMeasureCount) = *i;

    lNodes.push_back(
            RFNode(
                    pRFNode->mac,
                    pRFNode->zone,
                    pRFNode->subZone,
                    pRFNode->unit,
                    pRFNode->pwm,
                    pRFNode->led,
                    pRFNode->network,
                    pRFNode->lastContact,
                    pRFNode->ioConfiguration,
                    nNodeMeasureCount
            )
    );

希望有一天它会对某人有所帮助!

【讨论】:

你让我免于数小时的头疼。

以上是关于ORM 获取连接表的行数的主要内容,如果未能解决你的问题,请参考以下文章

sql(join on 和where的执行顺序)

sql(join on 和where的执行顺序)

sql(join on 和where的执行顺序)

sql语句中join、left join 、right join有啥区别?

查询以获取雪花中数据库中所有表的行数

Oracle_SQL 连接和子查询