diff --git a/Documentation/libtracefs-sql.txt b/Documentation/libtracefs-sql.txt
index 7b616fa..91c99d7 100644
--- a/Documentation/libtracefs-sql.txt
+++ b/Documentation/libtracefs-sql.txt
@@ -42,7 +42,7 @@ with a detailed message on any type of parsing error, including fields that do n
 to an event, or if the events or fields are not properly compared.
 
 The example program below is a fully functional parser where it will create a synthetic
-event from a SQL syntax passed in via the command line or a file. 
+event from a SQL syntax passed in via the command line or a file.
 
 The SQL format is as follows:
 
diff --git a/Makefile b/Makefile
index 96d7f55..7f382c3 100644
--- a/Makefile
+++ b/Makefile
@@ -364,11 +364,21 @@ $(bdir)/libtracefs.so.$(TRACEFS_VERSION): force
 	$(Q)mkdir -p $(bdir)
 	$(Q)$(MAKE) -C $(src)/src libtracefs.so
 
+$(bdir)/sqlhist.c: Documentation/libtracefs-sql.txt
+	cat $< | sed -ne '/^EXAMPLE/,/FILES/ { /EXAMPLE/,+2d ; /^FILES/d ;  /^--/d ; p}' > $@
+
+$(bdir)/sqlhist.o: $(bdir)/sqlhist.c
+	$(CC) -g -Wall -c -o $@ $^ -Iinclude/ $(LIBTRACEEVENT_INCLUDES)
+
+sqlhist: $(bdir)/sqlhist.o $(LIBTRACEFS_STATIC)
+	$(CC) -o $@ $^ $(LIBTRACEEVENT_LIBS)
+
 clean:
 	$(MAKE) -C $(src)/utest clean
 	$(MAKE) -C $(src)/src clean
 	$(RM) $(TARGETS) $(bdir)/*.a $(bdir)/*.so $(bdir)/*.so.* $(bdir)/*.o $(bdir)/.*.d
 	$(RM) $(PKG_CONFIG_FILE)
 	$(RM) $(VERSION_FILE)
+	$(RM) $(bdir)/sqlhist.o $(bdir)/sqlhist.c sqlhist
 
 .PHONY: clean
diff --git a/src/tracefs-hist.c b/src/tracefs-hist.c
index c3aecf9..7f9cf38 100644
--- a/src/tracefs-hist.c
+++ b/src/tracefs-hist.c
@@ -1468,7 +1468,7 @@ tracefs_synth_get_start_hist(struct tracefs_synth *synth)
 			hist = tracefs_hist_alloc(tep, system, event,
 						  key, type);
 			if (!hist)
-				break;
+				return NULL;
 		}
 	}
 
diff --git a/src/tracefs-sqlhist.c b/src/tracefs-sqlhist.c
index 1a3cf37..6224677 100644
--- a/src/tracefs-sqlhist.c
+++ b/src/tracefs-sqlhist.c
@@ -36,7 +36,8 @@ enum alias_type {
 struct field {
 	struct expr		*next;	/* private link list */
 	const char		*system;
-	const char		*event;
+	const char		*event_name;
+	struct tep_event	*event;
 	const char		*raw;
 	const char		*label;
 	const char		*field;
@@ -515,89 +516,175 @@ __hidden int table_start(struct sqlhist_bison *sb)
 	return 0;
 }
 
-static int update_vars(struct sql_table *table, struct field *event)
+static int test_event_exists(struct tep_handle *tep,
+			     struct sqlhist_bison *sb,
+			     struct expr *expr, struct tep_event **pevent)
+{
+	struct field *field = &expr->field;
+	const char *system = field->system;
+	const char *event = field->event_name;
+
+	if (!field->event)
+		field->event = tep_find_event_by_name(tep, system, event);
+	if (pevent)
+		*pevent = field->event;
+
+	if (field->event)
+		return 0;
+
+	sb->line_no = expr->line;
+	sb->line_idx = expr->idx;
+
+	parse_error(sb, field->raw, "event not found\n");
+	return -1;
+}
+
+static int test_field_exists(struct tep_handle *tep,
+			     struct sqlhist_bison *sb,
+			     struct expr *expr)
+{
+	struct field *field = &expr->field;
+	struct tep_format_field *tfield;
+	char *field_name;
+	const char *p;
+
+	if (!field->event) {
+		if (test_event_exists(tep, sb, expr, NULL))
+			return -1;
+	}
+
+	/* The field could have a conversion */
+	p = strchr(field->field, '.');
+	if (p)
+		field_name = strndup(field->field, p - field->field);
+	else
+		field_name = strdup(field->field);
+
+	if (!field_name)
+		return -1;
+
+	if (!strcmp(field_name, TRACEFS_TIMESTAMP) ||
+	    !strcmp(field->field, TRACEFS_TIMESTAMP_USECS))
+		tfield = (void *)1L;
+	else
+		tfield = tep_find_any_field(field->event, field_name);
+	free(field_name);
+
+	if (tfield)
+		return 0;
+
+	sb->line_no = expr->line;
+	sb->line_idx = expr->idx;
+
+	parse_error(sb, field->raw,
+		    "Field '%s' not part of event %s\n",
+		    field->field, field->event_name);
+	return -1;
+}
+
+static int update_vars(struct tep_handle *tep,
+		       struct sql_table *table,
+		       struct expr *expr)
 {
 	struct sqlhist_bison *sb = table->sb;
-	struct expr *expr;
+	struct field *event_field = &expr->field;
+	struct tep_event *event;
 	struct field *field;
 	const char *label;
-	const char *p, *r;
-	char *system;
-	int len;
+	const char *raw = event_field->raw;
+	const char *event_name;
+	const char *system;
+	const char *p;
+	int label_len = 0, event_len, system_len;
 
-	p = strchr(event->raw, '.');
+	p = strchr(raw, '.');
 	if (p) {
-		system = strndup(event->raw, p - event->raw);
-		if (!system)
+		char *str;
+
+		str = strndup(raw, p - raw);
+		if (!str)
 			return -1;
-		event->system = store_str(sb, system);
-		free(system);
-		if (!event->system)
+		event_field->system = store_str(sb, str);
+		free(str);
+		if (!event_field->system)
 			return -1;
 		p++;
 	} else {
-		p = event->raw;
+		p = raw;
 	}
 
-	event->event = store_str(sb, p);
-	if (!event->event)
+	event_field->event_name = store_str(sb, p);
+	if (!event_field->event_name)
+		return -1;
+
+	if (test_event_exists(tep, sb, expr, &event))
+		return -1;
+
+	if (!event_field->system)
+		event_field->system = store_str(sb, event->system);
+
+	if (!event_field->system)
 		return -1;
 
-	if (!event->label)
-		event->label = event->event;
+	label = event_field->label;
+	if (label)
+		label_len = strlen(label);
+
+	system = event_field->system;
+	system_len = strlen(system);
 
-	label = event->label;
-	len = strlen(label);
+	event_name = event_field->event_name;
+	event_len = strlen(event_name);
 
 	for_each_field(expr, field, table) {
+		int len;
+
 		field = &expr->field;
 
 		if (field->event)
 			continue;
 
-		p = strchr(field->raw, '.');
-		if (p) {
-			/* Does this field have a system */
-			r = strchr(p + 1, '.');
-			if (r) {
-				/* This has a system, and is not a alias */
-				system = strndup(field->raw, p - field->raw);
-				if (!system)
-					return -1;
-				field->system = store_str(sb, system);
-				free(system);
-				if (!field->system)
-					return -1;
-
-				/* save the event as well */
-				p++;
-				system = strndup(p, r - p);
-				if (!system)
-					return -1;
-				field->event = store_str(sb, system);
-				free(system);
-				if (!field->event)
-					return -1;
-				r++;
-				field->field = store_str(sb, r);
-				goto check_timestamps;
-			}
+		raw = field->raw;
+
+		/*
+		 * The field could be:
+		 *     system.event.field...
+		 *     event.field...
+		 *     label.field...
+		 * We check label first.
+		 */
+
+		len = label_len;
+		if (label && !strncmp(raw, label, len) &&
+		    raw[len] == '.') {
+			/* Label matches and takes precedence */
+			goto found;
 		}
 
-		if (strncmp(field->raw, label, len))
-			continue;
+		if (!strncmp(raw, system, system_len) &&
+		    raw[system_len] == '.') {
+			raw += system_len + 1;
+			/* Check the event portion next */
+		}
 
-		if (field->raw[len] != '.')
+		len = event_len;
+		if (strncmp(raw, event_name, len) ||
+		    raw[len] != '.') {
+			/* Does not match */
 			continue;
+		}
+ found:
+		field->system = system;
+		field->event_name = event_name;
+		field->event = event;
+		field->field = raw + len + 1;
 
-		field->system = event->system;
-		field->event = event->event;
-		field->field = field->raw + len + 1;
- check_timestamps:
 		if (!strcmp(field->field, "TIMESTAMP"))
 			field->field = store_str(sb, TRACEFS_TIMESTAMP);
-		else if (!strcmp(field->field, "TIMESTAMP_USECS"))
+		if (!strcmp(field->field, "TIMESTAMP_USECS"))
 			field->field = store_str(sb, TRACEFS_TIMESTAMP_USECS);
+		if (test_field_exists(tep, sb, expr))
+			return -1;
 	}
 
 	return 0;
@@ -608,29 +695,29 @@ static int update_vars(struct sql_table *table, struct field *event)
  * selections can be fields and not mention the event itself.
  */
 static int update_fields(struct tep_handle *tep,
-			 struct sql_table *table, struct field *event_field)
+			 struct sql_table *table,
+			 struct expr *expr)
 {
+	struct field *event_field = &expr->field;
 	struct sqlhist_bison *sb = table->sb;
 	struct tep_format_field *tfield;
 	struct tep_event *event;
-	struct expr *expr;
 	struct field *field;
 	const char *p;
 	int len;
 
-	/* First update fields with aliases an such */
-	update_vars(table, event_field);
+	/* First update fields with aliases an such and add event */
+	update_vars(tep, table, expr);
 
-	/* The update_vars already updated event->system and event->event */
-	event = tep_find_event_by_name(tep, event_field->system,
-				       event_field->event);
 	/*
 	 * If event is not found, the creation of the synth will
 	 * add a proper error, so return "success".
 	*/
-	if (!event)
+	if (!event_field->event)
 		return 0;
 
+	event = event_field->event;
+
 	for_each_field(expr, field, table) {
 		const char *field_name;
 
@@ -659,7 +746,8 @@ static int update_fields(struct tep_handle *tep,
 			continue;
 
 		field->system = event_field->system;
-		field->event = event_field->event;
+		field->event_name = event_field->event_name;
+		field->event = event;
 		field->field = field_name;
 	}
 
@@ -746,7 +834,7 @@ static void assign_match(const char *system, const char *event,
 	rval = &match->rval->field;
 
 	if (lval->system == system &&
-	    lval->event == event) {
+	    lval->event_name == event) {
 		*start_match = lval->field;
 		*end_match = rval->field;
 	} else {
@@ -772,7 +860,7 @@ static int build_compare(struct tracefs_synth *synth,
 	rval = &compare->rval->field;
 
 	if (lval->system == system &&
-	    lval->event == event) {
+	    lval->event_name == event) {
 		start_field = lval->field;
 		end_field = rval->field;
 		calc = TRACEFS_SYNTH_DELTA_START;
@@ -829,12 +917,12 @@ static int do_verify_filter(struct sqlhist_bison *sb, struct filter *filter,
 	 */
 	if (!*system && !*event) {
 		*system = filter->lval->field.system;
-		*event = filter->lval->field.event;
+		*event = filter->lval->field.event_name;
 		return 0;
 	}
 
 	if (filter->lval->field.system != *system ||
-	    filter->lval->field.event != *event)
+	    filter->lval->field.event_name != *event)
 		return verify_filter_error(sb, filter->lval, *event);
 
 	return 0;
@@ -1035,45 +1123,6 @@ static int build_filter(struct tep_handle *tep, struct sqlhist_bison *sb,
 	return ret;
 }
 
-static int test_event_exists(struct tep_handle *tep, struct sqlhist_bison *sb,
-			     struct expr *expr, struct tep_event **pevent)
-{
-	const char *system = expr->field.system;
-	const char *event_name = expr->field.event;
-	struct tep_event *event;
-
-	event = tep_find_event_by_name(tep, system, event_name);
-	if (pevent)
-		*pevent = event;
-	if (event)
-		return 0;
-
-	sb->line_no = expr->line;
-	sb->line_idx = expr->idx;
-
-	parse_error(sb, expr->field.raw, "event not found\n");
-	return -1;
-}
-
-static int test_field_exists(struct tep_handle *tep, struct sqlhist_bison *sb,
-			     struct expr *expr)
-{
-	struct tep_event *event;
-
-	if (test_event_exists(tep, sb, expr, &event))
-		return -1;
-
-	if (trace_verify_event_field(event, expr->field.field, NULL))
-		return 0;
-
-	sb->line_no = expr->line;
-	sb->line_idx = expr->idx;
-
-	parse_error(sb, expr->field.raw, "Field '%s' not part of event %s\n",
-		    expr->field.field, expr->field.event);
-	return -1;
-}
-
 static void *field_match_error(struct tep_handle *tep, struct sqlhist_bison *sb,
 			       struct match *match)
 {
@@ -1233,11 +1282,11 @@ static int verify_field_type(struct tep_handle *tep,
 	sb->line_no = expr->line;
 	sb->line_idx = expr->idx;
 
-	event = tep_find_event_by_name(tep, field->system, field->event);
+	event = tep_find_event_by_name(tep, field->system, field->event_name);
 	if (!event) {
 		parse_error(sb, field->raw,
 			    "Event '%s' not found\n",
-			    field->event ? : "(null)");
+			    field->event_name ? : "(null)");
 		return -1;
 	}
 
@@ -1339,12 +1388,12 @@ static struct tracefs_synth *build_synth(struct tep_handle *tep,
 
 	/* This could be a simple SQL statement to only build a histogram */
 	if (!table->to) {
-		ret = update_fields(tep, table, &table->from->field);
+		ret = update_fields(tep, table, table->from);
 		if (ret < 0)
 			return NULL;
 
 		start_system = table->from->field.system;
-		start_event = table->from->field.event;
+		start_event = table->from->field.event_name;
 
 		synth = synth_init_from(tep, start_system, start_event);
 		if (!synth)
@@ -1352,12 +1401,16 @@ static struct tracefs_synth *build_synth(struct tep_handle *tep,
 		goto hist_only;
 	}
 
-	ret = update_vars(table, &table->from->field);
+	ret = update_vars(tep, table, table->from);
+	if (ret < 0)
+		return NULL;
+
+	ret = update_vars(tep, table, table->to);
 	if (ret < 0)
 		return NULL;
 
 	start_system = table->from->field.system;
-	start_event = table->from->field.event;
+	start_event = table->from->field.event_name;
 
 	match = table->matches;
 	if (!match)
@@ -1368,7 +1421,7 @@ static struct tracefs_synth *build_synth(struct tep_handle *tep,
 		return NULL;
 
 	end_system = table->to->field.system;
-	end_event = table->to->field.event;
+	end_event = table->to->field.event_name;
 
 	assign_match(start_system, start_event, match,
 		     &start_match, &end_match);
@@ -1404,7 +1457,7 @@ static struct tracefs_synth *build_synth(struct tep_handle *tep,
 			ret = -1;
 			field = &expr->field;
 			if (field->system == start_system &&
-			    field->event == start_event) {
+			    field->event_name == start_event) {
 				int type;
 				type = verify_field_type(tep, table->sb, expr);
 				if (type < 0)
diff --git a/utest/tracefs-utest.c b/utest/tracefs-utest.c
index 645c84c..09bb8f2 100644
--- a/utest/tracefs-utest.c
+++ b/utest/tracefs-utest.c
@@ -51,7 +51,7 @@
 #define SQL_2_SQL	"select woke.next_pid as woke_pid, wake.common_pid as waking_pid from sched_waking as wake join sched_switch as woke on woke.next_pid = wake.pid"
 
 #define SQL_3_EVENT	"wakeup_lat"
-#define SQL_3_SQL	"select start.pid, end.next_prio as prio, (end.TIMESTAMP_USECS - start.TIMESTAMP_USECS) as lat from sched_waking as start join sched_switch as end on start.pid = end.next_pid"
+#define SQL_3_SQL	"select sched_switch.next_prio as prio, end.prev_prio as pprio, (sched.sched_waking.common_timestamp.usecs - end.TIMESTAMP_USECS) as lat from sched_waking as start join sched_switch as end on start.pid = end.next_pid"
 
 #define SQL_4_EVENT	"wakeup_lat_2"
 #define SQL_4_SQL	"select start.pid, end.next_prio as prio, (end.TIMESTAMP_USECS - start.TIMESTAMP_USECS) as lat from sched_waking as start join sched_switch as end on start.pid = end.next_pid where (start.prio >= 1 && start.prio < 100) || !(start.pid >= 0 && start.pid <= 1) && end.prev_pid != 0"
