CREATE TABLE test (
calculate_time int4 NULL,
status bool NULL
);
INSERT INTO test (calculate_time,status) VALUES
(10,true)
,(15,true)
,(20,true)
,(20,true)
,(5,false)
,(10,false)
,(15,false)
,(100,NULL)
,(200,NULL)
,(300,NULL)
;
使用此查询,它会平均所有calculated_time值。有没有办法可以告诉它只有status = true的平均值?我尝试添加一个where子句但会使失败和暂停的结果为0。
select
avg(calculate_time) as cal_time,
count(case when status = true then 1 end) as completed,
count(case when status = false then 1 end) as failed,
count(case when status is null then 1 end) as suspended
from test;
答案 0 :(得分:3)
您似乎理解条件聚合的概念。你也可以使用public abstract class CalendarPagerAdapter extends FragmentStatePagerAdapter {
private static final String TAG = LogUtils.makeLogTag(CalendarPagerAdapter.class);
protected DateTime mDateTime;
private final int mCount;
protected int mTodayPosition;
public static class CalendarContext {
public int mRange; // range = nb of days supported
public int mTodayPosition; // Today index in this area
public int mCurrentWeek; // Week number of today
public DateTime mFrom, mTo; // Compute from and to datetimes
public boolean mIsSundayFirstDay;
public CalendarContext(int area, int todayPosition, DateTime from, DateTime to,
int currentWeek, boolean isSundayFirstDay) {
mRange = area;
mTodayPosition = todayPosition;
mFrom = from;
mTo = to;
mCurrentWeek = currentWeek;
mIsSundayFirstDay = isSundayFirstDay;
}
}
public static CalendarContext computeAreaAndTodayPosition(int initialArea, int initialTodayPosition) {
// Compute min / max dates from now
DateTime from = new DateTime().minusDays(initialArea - initialTodayPosition).dayOfWeek().withMinimumValue();
DateTime to = new DateTime().plusDays(initialTodayPosition).dayOfWeek().withMaximumValue();
boolean isSundayFirstDay = false;
Calendar calendar = Calendar.getInstance(CompatUtils.getLocale(false));
if (calendar.getFirstDayOfWeek() == Calendar.SUNDAY) {
isSundayFirstDay = true;
from = from.minusDays(1);
to = to.minusDays(1);
}
LogUtils.LOGD("XXXX", "from dt=" + from.toString());
LogUtils.LOGD("XXXX", "to dt=" + to.toString());
// Compute nb days area supported
int daysRange = daysBetween(from, to).getDays() + 1;
LogUtils.LOGD("XXXX", "daysRange=" + daysRange);
// Compute today position
int todayPosition = daysBetween(from, DateTime.now().withTimeAtStartOfDay()).getDays() + 1;
LogUtils.LOGD("XXXX", "todayPosition=" + todayPosition);
int currentWeek = DateTime.now().getWeekOfWeekyear() - from.getWeekOfWeekyear();
LogUtils.LOGD("XXXX", "currentWeek=" + currentWeek);
return new CalendarContext(daysRange, todayPosition, from, to, currentWeek, isSundayFirstDay);
}
public CalendarPagerAdapter(FragmentManager mgr, int count, int todayPosition) {
super(mgr);
mDateTime = DateTime.now();
mCount = count;
mTodayPosition = todayPosition;
}
@Override
public int getCount() {
return mCount;
}
public boolean isTodayPosition(int position) {
return computeDifferenceDays(position) == 0;
}
public boolean isPastPosition(int position) {
return computeDifferenceDays(position) < 0;
}
public boolean isFuturPosition(int position) {
return computeDifferenceDays(position) > 0;
}
protected int computeDifferenceDays(int position) {
return position - getCalendarTodayPosition();
}
public long convertPositionToMs(int position) {
return convertPositionToMs(mDateTime, position);
}
public long convertMinPositionToMs() {
return convertPositionToMs(mDateTime, 0);
}
public long convertMaxPositionToMs() {
return convertPositionToMs(mDateTime, mCount - 1);
}
public String convertPositionToDate(int position) {
return TimeUnits.dateTimeToDateServer(new DateTime(convertPositionToMs(position)));
}
public long convertPositionToMs(DateTime datime, int position) {
int dayNum = computeDifferenceDays(position);
if (dayNum < 0)
return datime.minusDays(Math.abs(dayNum)).getMillis();
else if (dayNum > 0)
return datime.plusDays(Math.abs(dayNum)).getMillis();
else
return datime.getMillis();
}
public int convertMsToPosition(long millis) {
DateTime dtReceived = new DateTime(millis).withTimeAtStartOfDay();
return convertDateTimeToPosition(dtReceived);
}
public int convertDateTimeToPosition(DateTime dtReceived) {
DateTime now = DateTime.now().withTimeAtStartOfDay();
int nbDays = daysBetween(now, dtReceived).getDays();
return getCalendarTodayPosition() + nbDays;
}
public int getCalendarTodayPosition() {
return mTodayPosition;
}
public void shiftWithOffset(WeekDatePicker weekDatePicker, TextView weekDatePickerDayTextView,
DateTime currentSelectedDate, int offset) {
if (offset < 0 && mTodayPosition > 0) mTodayPosition += offset;
mDateTime = DateTime.now();
weekDatePicker.refreshTodayPosition();
weekDatePickerDayTextView.setText(TimeUnits.dateTimeToString(
currentSelectedDate, true, true, true, true, true));
}
}
表达式作为你选择中其他术语的平均值:
CASE
这是有效的,因为select
avg(case when status then calculate_time end) as cal_time,
count(case when status then 1 end) as completed,
count(case when not status then 1 end) as failed,
count(case when status is null then 1 end) as suspended
from test;
函数与大多数其他聚合函数一样,忽略AVG
个值。因此,NULL
不为真的记录,其status
值将被有效忽略,并且不会影响整体平均值。
其他注意事项:您可以直接在Postgres查询中使用布尔值,而无需将它们与calculate_time
进行比较。也就是说,以下两个true
表达式是等价的,第二个表达式更简洁:
CASE
答案 1 :(得分:2)
添加到@Tim的答案,因为Postgres 9.4你可以添加一个filter
子句来聚合函数调用,这可以节省你编写自己的case
的一些功能。表达式:
select
avg(calculate_time) filter (where status) as cal_time,
count(*) filter (where status) as completed,
count(*) filter (where not status) as failed,
count(*) filter (where status is null) as suspended
from test;