场景:在某个 SQL 中,得到一个中间表 m ,需要对 m 表 进行分条件的计数运算。为提高效率,不对 m 表做持久化处理。该如何做?
简单地说,即在一条语句中查询多个 COUNT 值。
一个解决方案是求助于 CASE 表达式
与 SUM 表达式
。
CASE 表达式
在 SQL 语句中, CASE 表达式
具有编程语言中的 if -- else
的功能。
|
CASE [base expression] WHEN w1 THEN rst_1 WHEN w2 THEN rst_2 [ELSE rst_3] END -- e.g: CASE x WHEN w1 THEN r1 WHEN w2 THEN r2 ELSE r3 END CASE WHEN x=w1 THEN r1 WHEN x=w2 THEN r2 ELSE r3 END |
关键字 CASE
与 WHEN
之间的可选表达式称为 base expression
。WHEN
与 THEN
组成WHEN 表达式
,THEN
关键词后跟的是 WHEN 表达式的 值
。还可以包括 ELSE 表达式
,它是可选的
- 在不使用 base 表达式的情况下,每个 WHEN 表达式从左到右依次计算布尔值, CASE 表达式的值为第一个为 真值 的 WHEN 表达式的值。如果没有值为真的 WHEN 表达式,CASE 表达式的值为 ELSE 表达式值。如果即没有值为真的 WHEN 表达式,也没有 ELSE 表达式,即么 CASE 表达式的结果为
NULL
- 在有 base 表达式的情况下,base 表达式会且仅会计算一次,然后从左到右依次与 WHEN 表达式做逻辑运算,第一个运算结果为真的WHEN 表达式的值即为 CASE 表达式的值。如果没有匹配的WHEN表达式,那么 ELSE 表达式的值即为CASE语句的值。若连 ELSE 表达式也没有,即么 CASE 表达式的值即为
NULL
SUM 表达式
啥?
实践
注:本实践使用 sqlite。
|
create table tb(name TEXT, age INTEGER, sex INTEGER); INSERT INTO tb VALUES('Tom',13,1); INSERT INTO tb VALUES('Aom',13,1); INSERT INTO tb VALUES('Bom',18,0); INSERT INTO tb VALUES('Com',22,1); INSERT INTO tb VALUES('Dom',23,0); |
现在要计算出 tb 表中 1. 有多少男性,2. 有多少儿童 3. 共多少人。SQL 如下:
|
SELECT count(*) AS total, SUM(CASE sex WHEN 1 THEN 1 ELSE 0 END) man, SUM(CASE WHEN age < 14 THEN 1 ELSE 0 END) child FROM tb |
提示:本文中的 Demo 已 push 到 github,可忽略本文直接到 我的github 中查看代码。
Qt 提供了 QuickControl TreeView
。但是比较奇葩的是该控件不能直接使用,而需要用户自己扩展实现。
官方给出了一个示例如下:
|
TreeView { TableViewColumn { title: "Name" role: "fileName" width: 300 } TableViewColumn { title: "Permissions" role: "filePermissions" width: 100 } model: fileSystemModel } |
它声明了一个 TreeView控件,该控件有 2 列,分别为 Name 和 Permissions,还有一个名为 fileSystemModel 的 model
。对用户来说,这里的 model 是一个关键性的对象,它需要用户使用 C++ 实现 ,并注册到 qml 中供 TreeView 使用。按官方的说法, model 是一个 为 tree view 提供数据的属性,它包含了 tree view 将要展示的数据。
用户的 model 必须继承于 QAbstractItemModel
类。
该类是一个抽象类,在运行中,treeview 从该类中获取用户数据,再在UI上展示。该类有如下纯虚函数,必须在子类中实现:
|
virtual int columnCount(const QModelIndex &parent = QModelIndex()) const = 0; virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const = 0; virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const = 0; virtual QModelIndex parent(const QModelIndex &index) const = 0; virtual int rowCount(const QModelIndex &parent = QModelIndex()) const = 0; |
继续阅读
上一次说到了在 django 中集成 tinymce。但在使用过程中发现功能不够强大。如自定义css, 上传文件等功能缺失,所以转向功能更全的 ckeditor
该项目在github上开源。
基本按照 github 上的简介就可以将其集成到项目里。但也有一些坑:
语言设置为中文
以下设置一个都不能少:
|
LANGUAGE_CODE = 'en-us' TIME_ZONE = 'Asia/Shanghai' USE_I18N = True LANGUAGES = [ ('en', 'English'), ('zh-cn', 'Chinese'), ] MIDDLEWARE_CLASSES = [ … 'django.middleware.locale.LocaleMiddleware', ] |
上传图片
settings.py
中以下设置
|
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/') MEDIA_URL = '/media/' CKEDITOR_UPLOAD_PATH = "uploads/" INSTALLED_APPS = [ … "ckeditor_uploader", ] |
其中 CKEDITOR_UPLOAD_PATH
必须是相对路径,相对基地址为 MEDIA_URL
在 model 中使用时,使用 from ckeditor.fields import RichTextField
, 在 form 中使用时,使用 from ckeditor_uploader.fields import RichTextUploadingFormField
继续阅读
关于 C++ 多线程编程一的些基本知识可以参考本博客的《C++11/14 新特性(多线程)》 ,《Unix线程基础》。本章不是多线程编程教程,而是个人经验的一些总结。这些经验有一些可能是不正确的,希望在今后的编程中实践、改进。
线程同步的四项基本原则:
- 最低限度地共享对象。对象尽量不要暴露给别的线程,如果需要暴露,优先考虑 immutable对象。否则尽量使用同步措施来充分地保护它
- 尽量使用高级地并发编程构件,如 任务队列、生产者消费者模式等
- 只用非递归的互斥器和条件变量,慎用读写锁,尽量少用信号量
- 除了使用
atomic
整数外,不要自己编写 lock-free 代码,也不要用"内核级"同步原语
互斥器 Mutex
mutex 是最常用的同步原语,它保护一个临界区,任何时候最多只能有一个线程能够访问 mutex 保护的域。使用 mutex 主要是为了保护共享数据。一般原则有:
- 使用
RAII
手法封装 mutex 的创建、销毁、加锁、解锁操作,充分保证锁的有效期等于其作用域,而不会因为中途返回或异常而忘记解锁。这类似于 Java 的synchronized
或 C# 的 using
语句。
- 使用非递归的 mutex
- 尽量不要人为地调用
lock()
和 unlock()
函数,将这些操作交给栈上的 guard
对象,利用其构造与析构函数。
- 不要跨线程地加解锁,避免在不同的函数中分别加锁\解锁,避免在不同的语句分支中加锁\解锁
- 每当构造 guard 对象时,需要考虑栈上已有的锁,防止因加锁顺序不同而导致死锁
- 避免跨进程的 mutex, 进程间通讯尽量使用
TCP sockets
只使用非递归地 mutex
继续阅读
对C++中 using关键字的几种用法的总结:
1. using 声明
using 声明 (using declaration)
是将命名空间中单个名字注入到当前作用域的机制,使得在当前作用域下访问另一个作用域下的成员时无需使用限定符 ::
|
// ... { using std::map map<int, std::string> the_map; //ok } map<int, std::string> the_map2; //error |
using 声明将其它 namespace 的成员引入本命名空间的 当前作用域 (包括其嵌套作用域) 。一个 using 声明一次只引入一个命名空间成员,它使得无论程序中使用哪些名字,都非常准确。
利用 using 声明,可以改变派生类对父类成员的访问控制:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
class Base{ protected: int bn1; int bn2; }; class Derived: private Base{ public: using Base::bn1; }; class DerivedAgain: public Derived{ }; int main(){ Derived d; DerivedAgain da; d.bn1 = 1; d.bn2 = 2; //error, 'bn2' is a private member of 'Base' da.bn1 = 3; //ok std::cout<<d.bn1<<std::endl; return 0; } |
尽管 Derived 对 base 是私有继承,但通过 using 声明,我们还是可以在 Derived 中访问其成员,且后续的继承同样不受 private 限定的影响。
继续阅读